Skip to content

深分页性能 ​

问题现象 ​

第一页很快,第几万页耗时明显增加;返回只有 20 行但扫描和回表数量巨大。

适用环境 ​

MySQL 8、InnoDB;列表需要按 ID 或组合键向后浏览。

本文是可复用的排障示例,不代表某次个人生产事故。命令中的名称、账号和数据均为示例,执行前请替换为已确认的目标。

复现或诊断步骤 ​

  1. 比较 LIMIT 0,20 与 LIMIT 200000,20 的扫描与延迟。
  2. 检查排序能否利用索引,确认过滤条件是否仍需要大量回表。
  3. 明确用户是否真的需要任意页跳转,还是只需上一页、下一页和导出。

原因分析 ​

OFFSET 不能直接定位第 N 条满足条件的结果,数据库仍需读取并跳过前面的记录。宽行查询还会放大回表成本,索引只能缓解部分开销。

修复示例 ​

sql
-- 使用上一页末行 ID,排序和过滤需一致
SELECT id, title
FROM article
WHERE id > :last_id AND status = 'PUBLISHED'
ORDER BY id
LIMIT 20;

-- 必须保留偏移跳转时,可先在窄索引中定位 ID
SELECT a.id, a.title
FROM article a
JOIN (
  SELECT id FROM article
  WHERE status = 'PUBLISHED'
  ORDER BY id LIMIT 200000, 20
) page ON page.id = a.id
ORDER BY a.id;

优先采用游标分页并为 (status,id) 等真实访问路径建立合适索引。延迟关联只能减少宽行回表,仍要跳过大量索引项。报表导出用分批游标或异步任务,避免用无限扩大 pageSize 的方式拉全量。

验证方法 ​

测试首页、中间页、尾页及并发写入;核对过滤条件不变时游标无重复。比较数据库读取行数与接口内存,记录任意跳页功能的产品取舍。

常见误区 ​

MAX(id) 不等于总行数。游标通常不能直接跳到第 1000 页;排序为时间时只带 ID 也不够,需携带完整稳定排序键。

官方参考链接 ​

相关分类:数据库与缓存 · 全部笔记