1-游标/书签分页
sql
-- 首次查询
SELECT * FROM orders ORDER BY create_time LIMIT 10;
-- 记录最后一条的 create_time = '2024-01-15 10:30:00'
-- 下一页(瞬间定位,与页码无关)
SELECT * FROM orders
WHERE create_time > '2024-01-15 10:30:00'
ORDER BY create_time LIMIT 10;
与传统分页的区别:
| 传统分页 | 游标分页 |
|---|---|
LIMIT offset, size |
WHERE 游标字段 > 上次值 LIMIT size |
| 依赖偏移量(第几页) | 依赖锚点(从哪条开始) |
| 页码越深越慢 | 性能恒定,与深度无关 |
适用场景:
| 场景 | 方案 | 原因 |
|---|---|---|
| 常规后台(< 1000 页) | LIMIT offset, size + 索引 |
需要支持跳页,数据量可控 |
| 大数据后台(> 10w 页) | 强制筛选条件 + 限制页码 | 避免深分页性能灾难 |
| 实时性要求低(如报表) | 游标分页 + 异步导出 | 全量导出场景 |
具体使用:
sql
-- 复合索引
INDEX idx_create_time_id (create_time, id)
-- 首次查询(无游标)
SELECT * FROM orders
ORDER BY create_time, id
LIMIT 10;
-- 返回最后一条:create_time='2024-01-15 10:30:00', id=12345
-- 下一页(有游标)
SELECT * FROM orders
#当 create_time 可能重复时,必须加唯一字段(如 id)确保稳定排序
WHERE (create_time > '2024-01-15 10:30:00')
OR (create_time = '2024-01-15 10:30:00' AND id > 12345)
ORDER BY create_time, id
LIMIT 10;
游标的优势在于深分页时保持恒定性能
2-覆盖索引
索引中已经包含了查询所需的全部字段,查询可以直接从索引返回结果,不需要回表
3-延迟关联
先用索引快速定位需要的主键,再用这些主键去表里取完整数据
sql
# create_time索引
INDEX idx_create_time (create_time)
# 第一步:只在索引上分页,拿到主键集合
SELECT id
FROM orders
ORDER BY create_time
LIMIT 10000,10;
# 第二步:用这些主键去表里取完整行
SELECT *
FROM orders
WHERE id IN ( ...10个id... )
ORDER BY create_time;
# 只回表 10 次,而不是在分页过程中回表