別再用offset和limit分頁了

2021-10-14 15:23:15 字數 3877 閱讀 9791

終於要對mysql優化下手了,本文將對分頁進行優化說明,希望可以得到乙個合適你的方案

分頁這個話題已經是老生常談了,但是有多少小夥伴一邊是既希望優化的自己的系統,另一邊在專案上還是保持自己獨有的個性。

優化這件事是需要自己主動行動起來的,自己搞測試資料,只有在測試的路上才會發現更多你未知的事情。

本文咔咔也會針對分頁優化這個話題進行解讀。

這個資料庫結構就是咔咔目前線上專案的表,只不過咔咔將欄位名改了而已,還有將時間字段取消了。

資料庫結構如下

根據以上資訊可以看到目前表裡邊的資料有350萬記錄,接下來就針對這350w條記錄進行查詢優化。

先來寫乙個查詢的sql語句,先看一下查詢耗費的時間。

根據下圖可以看到查詢時間基本忽略不計,但是要注意的是limit的偏移量值。

於是我們要一步一步的加大這個偏移量然後進行測試,先將偏移量改為10000

可以看到查詢時間還是非常理想的。

為了節省時間咔咔將這個偏移量的值直接調整到340w。

這個時候就可以看到非常明顯的變化了,查詢時間猛增到了0.79s。

出現了這樣的情況,那肯定就需要進行優化了,拿起鍵盤就是幹。

提到分析sql語句,必備的知識點就是explain,如果對這個工具不會使用的可以去看看mysql的基礎部分。

根據下圖可以看到三條查詢語句都進行了表掃瞄。

都知道只要有關於分頁就必存在排序,那麼加乙個排序再來看一下查詢效率。

然後在進行對排序的語句進行分析檢視。

通過這裡看到當使用了排序時資料庫掃瞄的行數就是偏移量加上需要查詢的數量。

此時就可以知道的是,在偏移量非常大的時候,就像上圖案例中的limit 3400000,12這樣的查詢。

此時mysql就需要查詢3400012行資料,然後在返回最後12條資料。

前邊查詢的340w資料都將被拋棄,這樣的執行結果可不是我們想要的。

如果你都把本文看到了這裡,那怎麼會讓你失望,肯定是優化大偏移量的效能問題。

既然提到了優化,無非就那麼倆點,加索引,使用其它的方案來代替這個方案。

咔咔提供的這條資料表結構資訊,完全可以理解為就是圖書館的借閱記錄,欄位的什麼都不要去關心就可以了。

對於排序來說,在這種場景下是不會給時間加排序的,而是給主鍵加排序,並且由於新增測試資料的原因將時間欄位給取消了。

接下來使用覆蓋索引加inner join的方式來進行優化。

從上圖可以看到查詢時間從0.8s優化到了0.4s,但是這樣的效果還是不盡人意。

於是只能更換一下思路再進行優化。

既然優化最大偏移量這條路有點坎坷,能不能從其它方面進行入手。

估計有很多同學已經知道咔咔將要丟擲什麼話題了。

沒錯,就是使用where > id 然後使用limit。

先來測試一波結果,在寫具體實現方案。

根據上圖可以看到這種方式是十分可行的,分頁在300w條資料以後的查詢時間也基本忽略不計。

那麼這種方案要怎麼實現呢!

其實這個方案真的很簡單,只需要簡單的轉換一下思路即可。

當客戶端第一次獲取資料的時候就正常傳遞offset、limit倆個引數。

首次返回的資料就使用客戶端傳遞過來的offset、limit進行獲取。

當第一次的資料返回成功後。

客戶端第二次拉取資料時這個時候引數就發生改變了,就不能再是offset、limit了。

此時應該傳遞的引數就是第一次獲取的資料最後一條資料的id。

此時的引數就為last_id、limit。

後台獲取到last_id後就可以在sql語句中使用where條件 < last_id

咔咔這裡給的情況是資料在倒敘的情況下,如果正序就是大於last_id即可。

接下來咔咔使用乙個案例給大家直接明了的說明。

實戰案例

如下就是將要實戰演示的案例,例如首次使用page、limit獲取到了資料。

返回結果的最後一條資料的id就是3499984

此時如果在獲取第二條記錄就不是使用offset、limit了,就是傳遞last_id和limit了。

如下圖此時就是使用的where條件來進行直接過濾資料,條件就是id小於上次資料的最後一條id即可。

時間對比

假設現在要獲取最後一條資料

沒有優化之前

優化之後可以明顯的看到查詢時間的變化

關於limit優化簡單幾句話概述一下。

堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大網際網路中咔咔的文章能帶給你一絲絲幫助。我是咔咔,下期見。

求求你別再用offset和limit分頁了

不需要擔心資料庫效能優化問題的日子已經一去不復返了。隨著時代的進步,隨著野心勃勃的企業想要變成下乙個 facebook,隨著為機器學習 收集盡可能多資料的想法的出現,作為開發人員,我們要不斷地打磨我們的 api,讓它們提供可靠和有效的端點,從而毫不費力地瀏覽海量資料。如果你做過後台開發或資料庫架構,...

Limit 和 offset簡單實用

limit 起始條目索引 條目數 特點 起始條目索引從0開始,起始條目索引可省略 limit 條目數 offset 起始條目索引 特點 起始條目索引從0開始,起始條目索引可省略 例子select from 表名 limit 3,1 從第4條資料開始取數,取1條資料,即只取第四條 select fro...

MySQL中 limit和offset用法

mysql裡分頁一般用limit來實現 select from article limit 1,3 select from article limit 3 offset 1 上面兩種寫法都表示取2,3,4三條資料。當limit後面跟兩個引數的時候,第乙個數表示要跳過的數量,後一位表示要取的數量,例如...