優(yōu)化LIMIT分頁
在系統(tǒng)中需要進行分頁才做的時候,我們通常會使用LIMIT加上偏移量的辦法實現(xiàn)罐氨。
比如:
explain select * from orders limit 10 offset 10 ;
一個非常常見又令人頭疼的問題就是,在偏移量非常大的時候(翻頁到非常靠后的頁面)堵未,例如可能是LIMIT 10000,10這樣的查詢,這時MySQL需要查詢10020條記錄然后只返回最后20條盏触,前面10000條記錄都被拋棄渗蟹,這樣的代價非常高。
那么如何優(yōu)化這類查詢呢?
第一步
首先對于這個查詢select id from orders;
我們可以explain
一下
explain select id from orders;
會發(fā)現(xiàn)這是一個索引掃描(在存在輔助索引的情況下)赞辩,相對表掃描這
個是會快很多的
第二步
基與上面的理論那么先將需要的id取出來 然后做一個子查詢
select * from orders WHERE id >= (select id from orders order by id limit 1 offset 10000) limit 10;
不過這個查詢是基于ID自增的假設雌芽,如果ID不是自增, 那么可以通過INNER JOIN
來改寫
select * from orders INNER JOIN (select id from orders order by id LIMIT 10 offset 10000) t USING (id);
補充
-
分頁的顯示
- 如果有獲取數(shù)據(jù)總數(shù) 那么通過總數(shù)自然可以得到頁數(shù)
一般獲取數(shù)據(jù)總數(shù)是一個索引掃描,如果數(shù)據(jù)量很大在innodb下對于sql什么優(yōu)化的有段 - 如果沒有總數(shù) 那么獲取的時候多獲取一些數(shù)據(jù), 比如每頁20個 我獲取21個 如果能取到自然有下一頁
- 如果有獲取數(shù)據(jù)總數(shù) 那么通過總數(shù)自然可以得到頁數(shù)
-
還是很慢怎么解決
- 從業(yè)務考慮 是否真的需要這種翻頁辨嗽, 因為普通用戶的話很少會關心歷史數(shù)據(jù)
- 可以考慮按時間段分表
- 維護一根分頁表世落,這樣直接就可以獲得某也有多少數(shù)據(jù)
- 交給其他工具去做,不讓mysql做自己不擅長的事情
總結
優(yōu)化此類分頁查詢的一個最簡單的辦法就是盡可能地使用索引覆蓋查詢糟需,而不是查詢所有的列屉佳。然后根據(jù)需要做一個關聯(lián)操作再返回所需的列谷朝。對于偏移量很大的時候,這樣做的效率會提升很大武花。