問題:在業務中,分頁查詢的場景非常多見,比如腳本分批處理數據;比如頁面上需要分頁查看列表。
假設是按照自增主鍵排序后分頁,最開始的時候肯定沒問題:
SELECT * from table_name order by id desc limit 0,20;
OK, Time: 0.007000s
但是如果翻到后面,情況肯定就不好了...
SELECT * from table_name order by id desc limit 10000000,20; OK, Time: 15.588000s
具體耗時根據表的大小和數據庫服務器而不同,是否能接受也看業務的具體情況,下面我們看下這種情況是為什么,以及如何優化。
explain一下慢查詢語句,可以看到:

顯然rows就是查詢慢的罪魁禍首了,Handler_read_prev 10000019 Number of requests to read the previous row in key order. Mainly used to optimize ORDER BY ... DESC.
這里要注意,即使在有索引的情況下,limit...offset操作也會從頭掃數據。
接下來是解決方案:
利用索引覆蓋,可以省去回表的耗時。
SELECT * from table_name order by id desc limit 10000000,1; OK, Time: 17.751000s
SELECT id from table_name order by id desc limit 10000000,1;
OK, Time: 5.370000s
所以改成如下SQL一般會快一些:
SELECT * from table_name where id >= (SELECT id from t_movie_schedule order by id desc limit 10000000, 1) limit 1; OK, Time: 6.912000s
但是很迷的是上面這個SQL不太穩定,似乎沒有分開執行這兩個SQL快
SELECT id from table_name order by id desc limit 10000000, 1; SELECT * from table_name where id >= (635883593) limit 1;
先忽略掉上面這個問題,也可以考慮在代碼里去處理這個問題,分兩步來查詢。
至於為什么select id會更快,我們需要了解下聚簇索引和回表的概念,這篇博客講得很清楚:https://www.cnblogs.com/boluopabo/p/12869348.html
