分頁查詢
分頁查詢在查詢業(yè)務(wù)當(dāng)中十分常見的情況层宫。那么如何去做好分頁查詢呢焊虏。
排序
首先分頁查詢很重要的一點是排序际度。只有一個穩(wěn)定的排序
才能保證分頁數(shù)據(jù)的準(zhǔn)確性。
簡單解析一下排序的穩(wěn)定性:
比如說有數(shù)據(jù)結(jié)構(gòu)如下:
class P {
Integer age,
String name
}
有以下的一組數(shù)據(jù)作為輸入進(jìn)行排序:
[
{
'age' = 3,
'name' = "A"
},
{
'age' = 1,
'name' = "B"
},
{
'age' = 1,
'name' = "C"
}
]
在這里,如果按照age來排序届氢,如果會出現(xiàn):
[
{
'age' = 1,
'name' = "B"
},
{
'age' = 1,
'name' = "C"
},
{
'age' = 3,
'name' = "A"
}
]
和
[
{
'age' = 1,
'name' = "C"
},
{
'age' = 1,
'name' = "B"
},
{
'age' = 3,
'name' = "A"
}
]
這兩種結(jié)果。
如果兩種結(jié)果都會出現(xiàn)的排序稱為不穩(wěn)定排序
覆旭。如果只會出現(xiàn)一種情況的稱為穩(wěn)定排序
簡單來講退子,穩(wěn)定排序可以保證排序結(jié)果的唯一,那么分頁的時候可以避免出現(xiàn)重復(fù)數(shù)據(jù)
的情況--如果第一次分頁查詢的排序結(jié)果是第一種型将,翻到下一頁查詢的排序結(jié)果是第二種那么第二頁還會出現(xiàn)name=C的數(shù)據(jù)寂祥,出現(xiàn)重復(fù)數(shù)據(jù)。
排序穩(wěn)定性的決定因數(shù)
在相同的輸入數(shù)據(jù)的情況下七兜,排序的穩(wěn)定性和排序的算法是直接相關(guān)的丸凭。
常見的算法穩(wěn)定性如下:
1.冒泡排序:穩(wěn)定
2.選擇排序:不穩(wěn)定
3.插入排序:穩(wěn)定
4.快速排序:不穩(wěn)定
5.歸并排序:穩(wěn)定
6.基數(shù)排序:穩(wěn)定
7.希爾排序:不穩(wěn)定
8.堆排序:不穩(wěn)定
數(shù)據(jù)庫在涉及很大的數(shù)據(jù)集繼續(xù)排序的時候,會使用磁盤。包括使用快速排序惜犀,歸并排序在內(nèi)的排序算法铛碑。所以不保證排序的穩(wěn)定性。
所以應(yīng)該考慮更多的鍵值作為排序的標(biāo)準(zhǔn)虽界,保證排序的唯一性
汽烦。
像上面的例子為了保證排序的唯一性
,可以使用age+name來實現(xiàn)莉御。
這是無論使用MySql還是Oracle 做分頁都需要考慮的地方撇吞。
當(dāng)然有特殊的情況是:使用索引來排序。這種情況下一般都是有序的颈将。
但是你要考慮優(yōu)化器梢夯,某些情況下索引失效的情況。
MySql實現(xiàn)
前端傳頁碼+頁大小
select xx,xxx from T where 條件 order by order_column limit offset,size
這種的話需要保證where條件之后結(jié)果集足夠小晴圾,不然后面翻頁會有比較大的開銷
使用ID鍵值進(jìn)行翻頁
這種場景下颂砸,一般表有一個唯一鍵值ID。前端通過傳鍵值ID+上翻頁或者下翻頁的方式進(jìn)行查詢死姚。一般都不會有什么新能問題
--下翻頁
select xxx,xxxx from T where id > ID order by id limit size
--上翻頁
select * from (select xx,xxx from T where id < ID order by id desc limit size ) as a order a.id
oracle 實現(xiàn)
oracle由于沒有l(wèi)imit人乓,實現(xiàn)起來會更復(fù)雜一些,需要使用到rownum
前端傳頁碼+頁大小
select * from
(select rownum rn,t1.* from
(select xx,xxx from T where xxx=xxxx order by xxx) t1
where rownum < maxRowNum)t2
where t2.rn > offset
maxRowNum 是通過頁碼和頁大小計算出來的最大的行
使用ID鍵值進(jìn)行翻頁
這種場景下都毒,一般表有一個唯一鍵值ID色罚。前端通過傳鍵值ID+上翻頁或者下翻頁的方式進(jìn)行查詢。一般都不會有什么新能問題
--下翻頁
select * from (select xxx,xxxx from T where id > ID order by id ) where rownum < size
--上翻頁
select * from (select xx,xxx from T where id < ID order by id desc ) where rownum < size as a order a.id