首页/数据/SQL 速查/深分页优化:keyset 分页
本包目录(311 条)
查询基础33 条连接与子查询40 条聚合与窗口函数54 条函数速查60 条变更与事务52 条
性能与执行计划72 条

深分页优化:keyset 分页

OFFSET 很大时数据库仍要逐行跳过:改用“上一页最后一条的键”做条件,让每页都走索引定位。

SQL 速查数据更新于 2026-10-12

对比

对比
-- 深分页:OFFSET 100000 需要先跳过 10 万行
SELECT id, title, created_at
FROM posts
ORDER BY created_at DESC, id DESC
LIMIT 20 OFFSET 100000;

-- keyset:从上一页末条的 (created_at, id) 继续
SELECT id, title, created_at
FROM posts
WHERE (created_at, id) < ('2024-06-01 12:00:00', 88888)
ORDER BY created_at DESC, id DESC
LIMIT 20;
-- MySQL 与 PostgreSQL 都支持 (a,b) < (c,d) 行构造器比较
前提排序列与游标列要能唯一确定顺序(非唯一列追加主键)
翻页方式只适合顺序翻页;跳页需要额外的键映射或首末页方案
索引(created_at, id) 复合索引让下一页定位变成一次范围查找

易错点

  • 继续用大 OFFSET 翻到后几页:跳过行数的成本随页码增长,热点表上很快变慢
  • 排序键不唯一直接做 keyset:相等值行可能漏掉或重复,要把主键拼进游标

数据来源与参考

  • MySQL 8.0 Reference Manual · Row Constructor Expressions
  • PostgreSQL Documentation · Row and Array Comparisons
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌