MySQL分页查询优化
MySQL分页查询优化
引言
后台列表、文章分页是最常见的SQL场景。数据量小的时候LIMIT偏移量查询很快,数据到几十万、上百万行,深分页会明显变慢,甚至拖垮数据库。
为什么深分页慢
LIMIT 100000,20 会先扫描前100000行再丢弃,只返回20行,扫描行数越多IO开销越大。
优化方案一:子查询定位主键
先查出起始主键,再用主键关联取数据,避免回表扫描:
SELECT a.* FROM article a
INNER JOIN (
SELECT id FROM article ORDER BY id LIMIT 100000,20
) b ON a.id=b.id;
子查询走覆盖索引,速度明显提升。
优化方案二:游标/记住上一页最大ID
SELECT * FROM article
WHERE id > 100000
ORDER BY id LIMIT 20;
每次只查比上一页最后一条ID大的记录,不走大偏移,适合无限滚动。
其他优化点
- 分页排序字段必须建索引,避免filesort;
- 只查询需要的字段,不用SELECT *;
- 禁止前端跳转到任意深页,后台限制最大页码;
- 超大表考虑分表、搜索引擎承接列表。
总结
深分页慢的根源是大偏移扫描。优先用主键游标翻页,配合覆盖索引;传统offset分页用子查询优化。列表数据量极大时,交给ES等搜索方案更合理。