1. 程式人生 > >分頁效能

分頁效能

現在假如啊,主鍵為id且是自增的,並且是連續的(不存在斷點,),那麼,這個語句 select * from xx limit 20000,10   跟這句 select * from xx where id>20000 limit 10.

取出的是相同的結果,但是前者的效能要遠遠落後於後者。因為,前者雖然是取2萬往後的十條,但是,他是先取出2萬零10條,然後從結果中篩選出後十條。而後者是直接先定位到2萬條,然後再取後十條,也就是說,前者遍歷了2萬零10行資料,而後者精遍歷我們需要的那幾條 這就引出了分頁的效能的差異

 

就比如網站常見的每頁顯示十條資料,那我們在選擇sql語句的時候,就不應該這樣了:

第一頁顯示的資料:

select * from xx limit 0,10

第二頁顯示的資料:

select * from xx limit 10,10

第3頁顯示的資料:

select * from xx limit 20,10

這樣隨著顯示的頁數越來越大,查詢效能直線下降。

 

我們需要這樣:

第一頁顯示的資料:

select * from xx where id >00 limit 10

第二頁顯示的資料:

select * from xx where id>10 limit 10

第3頁顯示的資料:

select * from xx where id >20 limit 10

第n頁:

select * from xx where id>(n-1)*10 limit 10

 

但是這樣還有一個問題:

我們前面假設了,id是連續的,但實際上,Id是不連續的,比如要顯示的是一個個人主頁的微博,每頁同樣是顯示10條微博,他不可能一直是寫,他也可能把過去的某條微博給刪除了,那麼這個時候這條資料刪除了,id也不存在了,id也就不連續了,所以會出現這樣,第二頁的起始id可能是11,然後結束id變為了56.也就是說,對於多少多少頁,我們是無法立刻預知到這一頁的起始id和結束Id,那麼select * from xx where id>(n-1)*10 limit 10.這樣的語句顯然就不行了.如果訪客直接要訪問第200頁,那麼我們還得計算200頁的起始id

計算起始id:

select id from xx limit 2000,1 

 

有人會問了,你這個計算起始id,跟前面的第一種方案的分頁不一樣嗎?不一樣的,第一種方案是select * ,而這個只取id,如果是隻取索引,這種只需要查索引表就能查到,叫做覆蓋索引。覆蓋索引是select的資料列只用從索引中就能夠取得,不必讀取資料行

(關於索引的原理的知識點:select * from xx where id=2;他的執行過程是先讀取索引表,拿到id為2的物理指標,然後拿著這個指標,然後再到資料庫中獲取資料,)

那麼這種效率也是快的。

拿到第200也的起始值在進行查詢,兩個步驟用一條sql語句合起來就是:

select * from xx where id>(select id from xx limit 2000,1) limit 10

那麼這樣就實現了分頁查詢的效果。

但我們經常能看到,人家不光有頁數,還有上一頁,後一頁,那麼這個時候,就需要在程式碼中儲存當前頁面的最小id和最大id 

當訪客檢視後一頁的時候,執行sql

select * from xx where id > max_id limit 10;

當訪客檢視前一頁的時候,執行sql

select * from xx where id < min_id order by id desc limit 10;