LEAD/LAG函数不加速分页,其真实用途是获取相邻行数据;MySQL 8.0分页提速关键在于prefer_ordering_index参数调优、索引覆盖、延迟关联和游标分页。

LEAD 和 LAG 函数本身不加速分页查询,也不能替代 LIMIT 实现分页。把它们当作“MySQL 8.0 分页更快”的原因,是典型的概念混淆。
LEAD / LAG 的真实用途:查“相邻行”,不是“跳过前N行”
LEAD 和 LAG 是窗口函数,用于在已排序的结果集内获取当前行的上一行(LAG)或下一行(LEAD)的某个字段值。它们依赖 ORDER BY + OVER(),但不跳过数据、不限制返回条数、不优化偏移扫描。
例如:
SELECT id, name,
LAG(id) OVER (ORDER BY id) AS prev_id,
LEAD(name) OVER (ORDER BY id) AS next_name
FROM users;
这会返回全表所有行,每行附带前后行信息 —— 和分页(只取第10001–10010条)完全无关。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
真正让 MySQL 8.0 分页变快的关键点
-
prefer_ordering_index参数(MySQL 8.0.21+)
可关闭优化器对排序索引的过度偏好,避免因ORDER BY id强制走主键索引而放弃更高效的过滤索引(如WHERE status=1+INDEX(status))。- 开启时:
set optimizer_switch = "prefer_ordering_index=on"(默认) - 关闭时:
set optimizer_switch = "prefer_ordering_index=off",更适合 where 条件强、排序字段区分度低的场景
- 开启时:
索引覆盖 + 延迟关联(如
JOIN子查询只查id)
这才是解决LIMIT 1000000, 20慢的核心手段,和窗口函数无关游标分页(
WHERE id > ? ORDER BY id LIMIT 20)
利用有序主键跳过偏移量,彻底绕开LIMIT的扫描丢弃逻辑
容易踩的坑
把
ROW_NUMBER()当分页用(尤其搭配LEAD/LAG)ROW_NUMBER() OVER (ORDER BY id)会强制对全部匹配行排序编号,数据量大时内存暴涨、执行极慢,比LIMIT还差在分页 SQL 里无意义地加
LEAD/LAG
比如SELECT *, LEAD(name) OVER (...) FROM t WHERE ... LIMIT 10000, 20
→ 先全扫描满足条件的行生成窗口结果,再丢弃前10000条 → 雪上加霜忽略排序字段的唯一性
即使用了游标分页,若ORDER BY created_at且存在大量相同时间戳,WHERE created_at > ?仍可能漏/重数据;必须补唯一字段,如ORDER BY created_at, id
真正影响分页性能的,从来不是“能不能算出下一页名字”,而是“能不能不扫前一百万行”。










