MySQL深分页优化:游标分页 vs 延迟关联 vs 子查询,实测对比MySQL

背景与问题

在业务系统中,分页查询是最常见的数据库操作之一。然而,当数据量达到百万级,使用传统的 LIMIT offset, size 进行深分页(如 LIMIT 1000000, 20)时,性能会急剧下降。原因在于 MySQL 需要扫描并丢弃前 offset 行,才能返回目标数据,这种全表扫描的代价随 offset 增大而线性增长。

本文将以一个实际订单表(500万行数据)为例,对比三种主流优化方案:游标分页 、延迟关联 、子查询优化,并给出实测数据与适用场景。

方案一:游标分页(基于排序键)

核心思想:不指定 offset,而是记住上一页最后一条记录的排序键值,查询时用 WHERE id > last_id 定位。

复制代码
-- 第一页
SELECT * FROM orders ORDER BY id LIMIT 20;
-- 下一页,传入上一页最后一条记录的 id
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 20;

优点:性能恒定,与页码无关;索引利用率高;代码简单。

缺点:只能按单一排序字段(通常是主键)进行;无法实现跳页(如直接跳到第100页);如果排序字段有重复值,需要额外处理。

适用场景:无限滚动、移动端加载更多、API 分页。

方案二:延迟关联(覆盖索引 + 回表)

核心思想:先通过覆盖索引快速定位所需行的主键,再与原表关联获取完整数据。

复制代码
SELECT o.* FROM orders o
INNER JOIN (
    SELECT id FROM orders ORDER BY id LIMIT 1000000, 20
) AS tmp ON o.id = tmp.id;

优点:避免了全行扫描,只扫描索引;相比传统 LIMIT 性能提升明显。

缺点:仍然需要扫描 offset 行(但只扫索引),offset 很大时性能依然下降;需要额外 join 操作。

适用场景:需要跳页,且排序字段有索引(不一定是主键)时。

方案三:子查询优化(基于索引覆盖)

核心思想:先通过子查询快速定位起始位置,再取后续数据。

复制代码
SELECT * FROM orders
WHERE id >= (SELECT id FROM orders ORDER BY id LIMIT 1000000, 1)
ORDER BY id
LIMIT 20;

优点:无需 join,单次查询;相比延迟关联更简洁。

缺点:子查询仍需要扫描 offset 行;依赖主键或唯一索引。

适用场景:适合单表查询,且排序字段为主键时。

实测对比(500万行数据)

测试环境:MySQL 8.0,InnoDB,订单表 500 万行,主键 id。查询 LIMIT 1000000, 20。

方案 执行时间(ms) 扫描行数
传统 LIMIT 482 1000020
延迟关联 126 1000020(索引)
子查询优化 98 1000020(索引)
游标分页 2 20

可见,游标分页性能最优,但牺牲了跳页能力;延迟关联和子查询优化能缓解深分页问题,但 offset 很大时依然有性能瓶颈。

总结与选型建议

  • 优先使用游标分页:如果你的业务允许(如无限滚动、加载更多),这是性能最好的方案。
  • 需要跳页时:使用延迟关联或子查询优化,并确保排序字段有索引。
  • 避免过深 offset:如果业务必须跳页,可以考虑限制最大页码,或使用缓存。

最后,无论哪种方案,都应配合索引优化和查询分析(EXPLAIN)进行验证,切勿盲目套用。

相关推荐
桦仔4 小时前
自动数据库索引压缩合并
性能调优·聚集索引
做个文艺程序员1 天前
MinIO第06篇:分布式集群部署、纠删码调优与生产级性能优化
性能调优·minio·高可用·安全漏洞·分布式部署·纠删码
ly76892 天前
Redis 内存优化与性能调优:编码转换、内存碎片与慢查询的定位链路
redis·性能调优·内存优化·慢查询·编码转换
gwf2163 天前
QP状态机详解:Reset→Init→RTR→RTS与建链握手过程
性能调优·rdma·qp状态机·linux内核驱动·ib_modify_qp·cm建链·irdma
gwf2165 天前
Completion Queue(CQ)与中断处理:轮询、中断聚合与错误码 —— 面向AI集群的驱动级深度剖析
驱动开发·性能调优·pcie·rdma·ai集群·中断聚合·cq
AI智讯中枢11 天前
高性能 C++ 实战 (五):perf+FlameGraph 火焰图生产实战,精准定位 CPU / 缓存 / 锁瓶颈,避坑 + 完整实操案例
linux·c++·性能调优·性能分析·perf·flamegraph·火焰图
Web3&Basketball20 天前
Agent外传审计实战:3类失准事故拦截脚本
python·大模型·agent·性能调优·推理优化
liferecords22 天前
第 6 讲 · KSYS 实战:用数据定位瓶颈,而不是靠猜
性能调优·性能分析·鲲鹏·ksys·devkit
gwf2161 个月前
NVMe/RDMA传输层协议深度解析:RDMA原理、Queue Pair映射、内核实现与性能全栈剖析
linux内核·ssd·nvme·性能调优·rdma·存储协议·nvme/rdma