LIMIT分頁優化

2021-09-03 08:22:06 字數 1416 閱讀 1869

在系統中需要分頁的操作通常會使用limit加上偏移量的方法實現,同時加上合適的order by 子句。如果有對應的索引,通常效率會不錯,否則mysql需要做大量的檔案排序操作。

乙個非常令人頭疼問題就是當偏移量非常大的時候,例如可能是limit 10000,20這樣的查詢,這是mysql需要查詢10020條然後只返回最後20條,前面的10000條記錄都將被捨棄,這樣的代價很高。如果所有的頁面被訪問的頻率相同,那麼這樣的查詢平均需要訪問半個表的資料。要優化這樣的查詢,要麼實在頁面中限制分頁的數量,要麼是優化大偏移量的效能。

優化此類查詢的乙個最簡單的方法是盡可能的使用索引覆蓋掃瞄,而不是查詢所有的列。然後根據需要做一次關聯操作再返回所需的列。對於偏移量很大的時候這樣做的效率會得到很大提公升。對於下面的查詢:

select id, description from news order by title limit 50,5;

如果這個表非常大,那麼這個查詢可以改寫成如下的方式:

select news.id, news.description from news inner join (select id from news order by title limit 50,5) as mynew using(id);

這裡的「延遲關聯」將大大提公升查詢的效率,它讓mysql掃瞄盡可能少的頁面,獲取需要的記錄後再根據關聯列回原表查詢需要的所有列。這個技術也可以用在優化關聯查詢中的limit。

limit和offset的問題其實是offset的問題,它會導致mysql掃瞄大量不需要的行然後再拋棄。如果可以使用書籤記錄上次取資料的位置,那麼下次就可以直接從該位置開始掃瞄,這樣可以避免使用offset。例如:

select id, description from news where id >10000 limit 5;這樣做的好處是無論翻頁到多麼後面,其效能都會很好。

其他優化的辦法還包括使用預先計算的彙總表,或者關聯乙個冗餘表,冗餘表只需要包含主鍵列和需要排序的資料列。還可以使用sphinx優化一些搜尋操作。

還有一種做法就是做資料快取。先獲得並快取較多的資料,例如,快取一千條,然後每次分頁都從這個快取中獲得。

關於分頁的總條數:

分頁的時候另乙個常用的技巧是在limit語句中加上sql_call_found_rows提示(即hint),這樣就可以獲得去掉limit以後滿足條件的行數,因此可以作為分頁的總行數。但實際上mysql只有在掃瞄了滿足條件的所有行後才知道總行數。所以加上這個提示之後不管需不需要都會掃瞄所有的行,然後再拋棄掉不需要的行,而不是在滿足limit的行數後就終止掃瞄。所以該提示的代價可能非常高。

有時候也可以考慮explain的結果中的rows列的值作為結果集總數的近似值(實際上google的搜尋結果也是個近似值)。當需要精確的結果的時候再單獨使用count(*)來滿足需求。

不過可以查詢一次總行數並快取起來,這樣就不用每次都查詢一下總行數了。

**:

limit分頁優化

對於有大資料量的mysql表來說,使用limit分頁存在很嚴重的效能問題。查詢從第1000000之後的30條記錄 sql 1 平均用時6.6秒 select from cdb posts order by pid limit 1000000 30 sql 2 平均用時0.6秒 select from...

Limit分頁優化

1.直接用limit start,count分頁語句,也是我程式中用的方法 select from product limit start,count 當起始頁較小時,查詢沒有效能問題,我們分別看下從10,100,1000,10000開始分頁的執行時間 每頁取20條 如下 select from p...

優化limit分頁

問題 訂單資料大約90萬 每頁展示20條記錄,當直接點選尾頁時,呼叫服務超時 sql如下 select from t order salary where create time 2018 05 10 00 00 00 order by create time limit 900000,20 lim...