LIMIT 100000,20慢到超时?MySQL深分页的三种解法

来源:互联网 时间:2026-08-31

后台导出、爬虫采集、或者用户把列表翻到几千页——只要LIMIT的偏移量上了十万,查询就会肉眼可见地卡。很多人以为是数据太多撑不住,其实是MySQL的工作方式太老实:LIMIT 100000,20的意思是把前100020行都取出来,扔掉前100000行,只返回20行。偏移量越大,白干的活越多。

先复现确认:同样的查询,LIMIT 0,20毫秒级,LIMIT 500000,20十几秒,基本可以确诊深分页问题。

-- 慢的写法:偏移量越大越慢
SELECT id, title FROM articles
ORDER BY id DESC
LIMIT 500000, 20;
-- 实际扫描了50万零20行,扔掉50万行

解法一:游标分页,记住上一页最后一条的id,下一页从它之后取。这是根治方案,性能跟页码无关,翻到第几页都是毫秒级。

-- 游标分页:记住上一页末尾id=98765
SELECT id, title FROM articles
WHERE id < 98765
ORDER BY id DESC
LIMIT 20;
-- 永远只扫20行,翻到十万页也一样快

游标分页的局限是只能“上一页下一页”,跳页就废了。后台管理需要跳页的场景用解法二:延迟关联。先用覆盖索引把目标id找出来,再回表取整行数据,白干的活从“扫全行”降到“扫索引”。

-- 延迟关联:子查询只走索引
SELECT a.id, a.title, a.content
FROM articles a
JOIN (
SELECT id FROM articles
ORDER BY id DESC
LIMIT 500000, 20
) t ON a.id = t.id;
-- 子查询扫的是主键索引,比扫整行便宜一个量级

验证用EXPLAIN:延迟关联版本的执行计划里子查询应该显示Using index(覆盖索引),对比直接查询的rows估算值,差几个数量级就说明优化生效。

解法三最朴素:限制翻页深度。产品层面只允许翻前100页,再往后让用户用筛选或搜索定位。Google也只给你看前几十页,没人真需要第50000页的第3条数据。

我的排序建议:面向用户的前台直接上游标分页,一劳永逸;后台导出用延迟关联加limit分段;实在没条件改代码,就把max偏移量限制住。别让一条深分页SQL占着连接耗几十秒,它一个人就能把连接池拖垮。

数据来源:MySQL官方手册

相关文章

标签:

A5创业网 版权所有

返回顶部