1. MySQL超大分页问题本质剖析
当我们在处理海量数据分页时,经常会遇到这样的场景:用户需要查看第10000页的数据,每页显示20条记录。按照传统分页写法LIMIT 200000, 20,MySQL的执行过程实际上是这样的:
- 首先扫描全表或索引
- 找到满足条件的200000+20条记录
- 丢弃前200000条
- 返回最后的20条
这个过程中最致命的问题是"丢弃前200000条"这个操作。我曾经在一个订单系统中实测过,当offset达到50万时,查询耗时已经超过3秒,而offset到100万时直接超时。这是因为MySQL必须物理扫描这些记录,即使最终只需要返回少量数据。
重要提示:这种性能下降不是线性增长,而是近似指数级的。当offset超过某个临界值(通常是几十万量级)后,响应时间会突然飙升。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 游标分页:连续浏览场景的终极方案
2.1 实现原理与技术细节
游标分页(Keyset Pagination)的核心思想是:记住当前页最后一条记录的位置标记,下页查询时直接从该标记之后开始取数据。这个标记通常是具有唯一性且有序的字段,如自增ID、时间戳等。
假设我们有一个订单表,按创建时间倒序排列:
sql复制-- 第一页查询
SELECT * FROM orders ORDER BY created_at DESC, id DESC LIMIT 20;
-- 假设最后一行的created_at是'2023-05-20 15:30:00',id是10086
-- 下一页查询变为:
SELECT * FROM orders
WHERE (created_at < '2023-05-20 15:30:00')
OR (created_at = '2023-05-20 15:30:00' AND id < 10086)
ORDER BY created_at DESC, id DESC
LIMIT 20;
这里有几个关键点需要注意:
- 排序字段必须建立联合索引(如
INDEX(created_at, id)) - 对于可能重复的字段(如created_at),需要添加唯一字段(如id)作为二级排序
- WHERE条件要精确反映ORDER BY的逻辑
