mysql 深度分頁


mysql  分頁查詢使我們常見的需求 ,但是隨着頁數的增加查詢性能會逐漸下降,尤其是到深度分頁的情況。我們可以把分頁分為兩個步驟,1.定位偏移量,2.獲取分頁條數的 數據。

所以當數據較大頁數較深時就涉及一次需要耗費較長時間的操作。所以mysql深度分頁的 問題該如何解決呢 ?

首先我們來看一個簡單的查詢:

SELECT    * FROM events WHERE    date > '2010-01-01T00:00:00-00:00' AND event = 'editstart' ORDER BY date LIMIT 50000 50;
其大致的性能頁數查詢性能曲線如下:

 

 可以發現在一定頁數后時間延時非常明顯。結合相關文章我們的解決方式可以大致分為以下幾種.

思路:

  既然分頁查詢時,定位偏移量較慢,我們可不可以減少這個偏移量的定位,使其始終曲線的前半部分,即在較少偏移量的場景。

方法一:以結果作為條件,已查詢條件的變化換取分頁的不變。

  分頁查詢我們一般都是逐漸往后翻頁的,那么我們可以很清晰的知道,在當前查詢頁的最后一條數據的時間點,那么,以此時間點再查詢20條,那么 我們當前的頁數就同樣還是0,以時間點的推移換取頁數的不變,減少其偏移量的計算。

我們可以創建索引 index(date,id), id就是我們上一次的返回結果。

具體示例如下:

SELECT    *FROM    events	WHERE    (date,id) > ('2010-07-12T10:29:47-07:00',111866)        AND event = 'editstart' ORDER BY date, id LIMIT 50000 50

  以上方法的局限性:

  1.id最好是主鍵,是否有這樣自增長的字段,或者說帶順序變化特性的列。

  2.無法適應下一次分頁頁數與上一次相差較大,如由第一頁突然跳轉到50萬頁。

  優點:可以適合復雜查詢條件查詢的場景。不需要改變sql語句結構

方法二:

  采用子查詢模式,其原理依賴於覆蓋索引,當查詢的列,均是索引字段時,性能較快,因為其只用遍歷索引本身。我們自己創建的非主鍵索引,都是非聚集索引,其不包含非索引字段,所以數據結構較小,系統能快速遍歷。我們知道索引時b+樹結構,系統能很容易的知道866613,位於索引樹的位置。

##查詢語句
select id from product limit 866613, 20
##優化方式一
SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
##優化方式二
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id

  局限性:

  依賴於主鍵的自增長特性。

  不適合復雜查詢條件的分頁邏輯,復雜查詢條件很難做到,索引包含全部查詢字段,容易漏掉部分數據。

方法三:

  復合索引:其原理同樣是索引覆蓋的思想,只不過是其以查詢條件的一份作為索引,最終的索引字段是主鍵id。這種場景嚴格依賴於索引的順序。查詢的結果也不能包含非索引字段,需再走一次子查詢。

  可以參考博客:https://blog.csdn.net/yalishadaa/article/details/72861309

關於深度分頁:

針對復雜的查詢邏輯,一般從數據的 偏移量着手,減少偏移量的定位時間。

簡單的查詢邏輯,可以從索引覆蓋的思想着手,先確定查詢數據的主鍵id,再由id找相關的數據,索引能解決的 就不要加給業務邏輯了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM