分页性能取决于索引——深分页需排序字段有对应索引,否则全表扫描;推荐复合索引覆盖排序+过滤、Keyset游标分页替代OFFSET、主键续传适用于连续主键场景,并用覆盖索引减少回表。

SQL分页和索引强相关——没有合适索引的分页,尤其是深分页,性能会断崖式下跌。核心问题不在LIMIT本身,而在于数据库如何定位“第N页的第一行”。索引决定了这个定位是秒级还是秒杀级。
分页必须依赖可利用的排序索引
ORDER BY字段必须有对应索引,否则数据库只能全表扫描+临时排序(filesort),再丢弃前offset行。即使只取10条,也可能扫描百万行。
- 推荐用复合索引覆盖排序+过滤,例如:ORDER BY created_at DESC, id DESC → 索引 (created_at, id)
- 避免在排序字段上用函数,如 ORDER BY DATE(create_time),会导致索引失效
- 若分页同时带WHERE条件,把高频过滤字段放在联合索引最左侧(遵循最左前缀)
慎用OFFSET,优先Keyset分页(游标分页)
OFFSET越大,数据库越要“数着走”:跳过前N行才能拿到下一页。这不是跳转,是遍历。
- 替代方案:记录上一页最后一条的排序键值,下一页查 WHERE (created_at, id) < (‘2025-03-01’, 12345) LIMIT 10
- 要求排序字段组合必须唯一且稳定(推荐用时间+主键),避免漏数据或重复
- 适合Feed流、日志、消息列表等无需跳转任意页的场景
主键续传适用于简单有序场景
当按主键升序/降序分页,且主键连续、自增、无删除空洞时,可用主键范围直接切片:
- 例如:上一页最大id=9876,下一页查 WHERE id > 9876 ORDER BY id LIMIT 20
- 速度快、不依赖OFFSET,但无法跳转中间页(如直接翻到第100页)
- 注意:业务中主键常被逻辑删除或跳号,需确认是否真“连续”
覆盖索引减少回表,提升分页吞吐
分页查询若只涉及少量字段,可建覆盖索引,让数据库直接从索引中读完所有数据,不访问聚簇索引(表数据)。
- 例如:分页只查 id, title, created_at,建索引 (created_at, id, title)
- 联合索引顺序建议:先排序字段,再用于过滤的字段,最后是SELECT字段(满足覆盖)
- 注意索引宽度,避免过长字符串全字段入索引;长文本可用前缀索引










