MySQL深分页问题与优化思路

前言

大家好,这里是程序员阿亮

大家肯定都用limit进行过分页,这个分页实际上在MySQL之中是一个很笨拙的过程!很容易造成深分页问题!

一、limit深分页问题

假设你有一条这样的 SQL 语句:

sql 复制代码
SELECT * FROM orders ORDER BY create_time LIMIT 1000000, 10;

你主观上是不是认为MySQL 会直接跳到第 100 万行,然后拿出 10 条数据。但事实并非如此。

我们的MySQL会很笨拙地:

大量扫描: MySQL 必须从索引树上按顺序扫描获取 1,000,010(100万零10)条记录。

如果order by的字段是二级索引就会需要大量回表,如果没有,通过filesort也需要大量的回表查询,将100万数据放到sortbuffer里面或者临时文件进行排序在获取最后的10条!

查出这 100万零10 条完整的记录后,MySQL 会丢弃前 100 万条,只将最后的 10 条返回给你。

绝大部分的磁盘 I/O 和 CPU 算力都浪费在了那 100 万条最终要被丢弃的数据上,尤其是"回表"操作带来的大量随机磁盘读取,直接拖垮了性能。

二、优化思路

1.游标分页 / 标签分页(Seek Method)

适用场景: 移动端下拉刷新、瀑布流、或者不需要"跳页"(如直接跳转到第 100 页)的场景。

这是性能最好的分页方式。它的核心思想是:记住上一页最后一条数据的特征(通常是连续的自增 ID 或时间戳),作为下一页的查询条件。

比如说:

sql 复制代码
SELECT * FROM orders ORDER BY id LIMIT 1000000, 10;

优化后:

sql 复制代码
SELECT * FROM orders WHERE id > 1000050 ORDER BY id LIMIT 10;

这样就可以避免我们先获取前100万条数据后丢弃,直接通过索引去获取数据了!

2.子查询、延迟查询优化

适用场景: 必须保留"页码跳转"功能(比如 PC 端的传统分页组件)。

核心思想是:利用"覆盖索引"(Covering Index)极大地减少回表的开销。 我们先通过索引只查出需要的 ID,然后再用这些 ID 去关联原表获取完整数据。

优化前:

sql 复制代码
SELECT * FROM orders ORDER BY create_time LIMIT 1000000, 10;

优化后:

sql 复制代码
SELECT t1.* FROM orders t1
INNER JOIN (
    -- 这里的子查询只查主键 id,如果 create_time 有索引,就能完美命中覆盖索引,无需回表
    SELECT id FROM orders ORDER BY create_time LIMIT 1000000, 10
) t2 ON t1.id = t2.id;

通过这种方式,我们可以先在where条件建立联合索引,通过这个联合索引获取合适的ids,然后再去主键索引获取需要的10条数据,相对来说数据的开销就要小很多,因为在没有子查询的时候,我们的SQL需要获取所有的100万条数据,取出完整的行数据,然后在取最后10条

而我们的子查询则可以先获取符合条件的ids,通过我们的二级索引

然后再通过二级索引去主键索引获取数据,避免了对100万条数据的整行数据扫描。

  • 优点: 子查询中因为只查 id,避免了前 100 万条记录的回表操作,都在内存/索引中完成,性能提升非常明显。然后主查询只需要拿这 10 个 ID 回表查具体数据即可。

  • 缺点: 随着 offset 变得极其庞大(比如千万级别),子查询扫描索引的开销依然不小,只是缓解了痛点。


三、总结

实际上我们业务中使用子查询已经可以将数据在很大程度上进行性能优化了,通过减少数据量与IO来提高我们的性能,也可以通过瀑布分页来达到更高的性能需求,但是这种情况下也就不能满足跳页。

相关推荐
代码什么用4 小时前
Spring对IoC的实现
数据库·spring
hz567896 小时前
涉密视频会议设备配置指南:终端、音视频采集与配套设施选型
服务器·网络·数据库·安全·实时音视频·信息与通信·智能硬件
广州浮点FLOATLIC6 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
程序员Sunday6 小时前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql
半杯咖啡半行码6 小时前
Qt开发实战:数据库、MV 模式、QProcess与串口通信全攻略
数据库·qt
Yyyyyy~6 小时前
[ Mysql ] 库的操作
mysql
小米里的大麦6 小时前
16 MySQL 事务
数据库·mysql
西柚小萌新6 小时前
【LLM&&AI应用开发 八股文】--4.3.Agent智能体(下)
java·开发语言·数据库
Titan20247 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
邓工说电7 小时前
智慧断路器安全吗?数据加密、离线保护与合规认证全解读
大数据·数据库·人工智能·智能断路器·炜晔科技