后台列表翻到后面几十万页时接口超时,前面的页却很快。日志里能对上时间点,这种反而好排。

limit 偏移量大时数据库要先扫描并丢弃前面所有行,成本随页码线性增长。这一点先确认清楚,后面就不用反复试。

SELECT id, title FROM posts
WHERE id > 1000000 ORDER BY id LIMIT 20;
-- 延迟关联
SELECT p.* FROM posts p
JOIN (SELECT id FROM posts ORDER BY id LIMIT 1000000, 20) t ON p.id = t.id;

「MySQL 深分页」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

别只看报错的最后一行,往上看几行,真正的起因通常在上面。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。

把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。改完隔一天再看一次,当场正常不代表能稳住。

处理上按这个顺序:改用基于上次最大 id 的游标分页;必须跳页时用延迟关联先取主键;限制最大可翻页数。

结果对不对很好判断,深页查询耗时降到毫秒级,翻页结果与总数统计一致。

作者 9823189