如何实现MySQL百万级数据的查询?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 本文探讨了在MySQL中对百万级数据进行排序分页查询的优化策略。面对五百万条数据,传统的浅分页和深分页查询效率较低,尤其深分页因偏移量大导致性能显著下降。通过为排序字段添加索引、使用联合索引、手动回表等方法,有效提升了查询速度。最终建议根据业务需求选择合适方案:浅分页可加单列索引,深分页推荐联合索引或子查询优化,同时结合前端传递最后一条数据ID的方式实现高效翻页。

MySQL百万级数据排序分页查询

1. 需求

按照成绩降序排序,查询字段学号(id),姓名(name),分数(score),带排序的分页查询

数据大小:五百万条

2. 初始状态

浅分页:

sql

体验AI代码助手

代码解读

复制代码

# 浅分页
EXPLAIN
SELECT id, name, score from student order by score desc limit 5, 20;

执行效率:执行的为一个全表扫描,并且会额外执行Using filesort

Using filesort表示在索引之外,需要额外进行外部的排序动作。导致该问题的原因一般和order by有者直接关系,一般可以通过合适的索引减少或者避免

执行时间:1.394s

深分页:

sql

体验AI代码助手

代码解读

复制代码

# 深分页
EXPLAIN
SELECT id, name, score from student order by score desc limit 4500000, 20;

执行效率:和浅分页一样

执行时间:6.071s

结论: 无论深分页还是浅分页,执行时间都是非常长的,并且深分页比浅分页的时间还要更长,因为浅分页的偏移量比较小,而深分页大,所以深分页的扫描行数要比浅分页多,所以时间更长

3. 优化查询1

order by的排序字段添加索引

sql

体验AI代码助手

代码解读

复制代码

# 为order by的排序字段添加索引
ALTER TABLE student ADD INDEX idx_score (score);

浅分页:

sql

体验AI代码助手

代码解读

复制代码

# 浅分页
EXPLAIN
SELECT id, name, score from student order by score desc limit 5, 20;

执行效率:直接使用索引,额外执行Backward index scan

Backward index scan 是 MySQL8针对上面场景的一个专用优化项,它可以从索引的后面往前面读,性能上比加索引提示要好的多。在 MySQL 中我们创建的索引,默认索引的叶子节点是从小到大排序的,而此时我们查询排序时,是从大到小,所以,在扫描时,就是反向扫描,就会出现 Backward index scan 。

执行时间:0.032s,加快的查询时间

深分页:

  1. 执行默认方式
    执行效率:走的还是一个全表扫描

    执行时间:5.962s,和不使用索引差别不大

  2. 让深分页强制走索引:FORCE INDEX (idx_score)

sql

体验AI代码助手

代码解读

复制代码

EXPLAIN
SELECT id, name, score from student FORCE INDEX (idx_score) order by score desc limit 4500000, 20;

执行效率:和浅分页相同

执行时间:82.011s,查询时间大大增加

结论:

  1. 优点:浅分页查询速度得到很好的提升
  2. 缺点:深分页查询速度没有明显变化,如果走强制索引,查询时间还会大大增加

分析: 在使用索引后,索引需要做一个回表操作,这个需要时间,而排序也需要时间,在执行深分页的时候,偏移量大,造成回表成本增大,所以这时候mysql会帮我们做一个优化,两者之间选一个最优的

4. 优化查询2

order by和select字段添加联合索引

sql

体验AI代码助手

代码解读

复制代码

# 创建联合索引
ALTER TABLE student ADD INDEX idx_score_name_id (score, name, id);

深分页:

sql

体验AI代码助手

代码解读

复制代码

# 深分页
EXPLAIN
SELECT id, name, score from student order by score desc limit 4500000, 20;

执行效率:使用索引,并且使用了覆盖索引(Using index)

执行时间:1.117,这里查询时间也是加快的很多

优点:深分页查询速度得到明显提升

缺点:新增一个查询字段时,索引就会失效

5. 优化查询3

删除联合索引,防止干扰

sql

体验AI代码助手

代码解读

复制代码

# 删除联合索引,防止干扰
drop index idx_score_name_id on student;

深分页:

sql

体验AI代码助手

代码解读

复制代码

EXPLAIN
SELECT t1.id, t1.name, t1.score from student t1 join
(select id from student order by score desc limit 4500000, 20) t2 on t1.id = t2.id;

执行效率:效执行里面的子查询,查询走的是索引,然后再从子查询中获取到的20条数据在进行查询,查询走的是PRIMARY

查询时间:1.054s

优点: 深查询得到明显提升

缺点: 当子查询结果集过多时不推荐使用

6. 优化查询4

先将所有数据排序好,先根据score进行降序排序,score相同的情况下再根据id进行降序排序,然后在取前20条数据,这里还得和前端配合,前端每次发送请求都携带最后一个的id值和score值

sql

体验AI代码助手

代码解读

复制代码

EXPLAIN
SELECT id, name, score from student
WHERE id < 10000000 AND score <= 100
ORDER BY score DESC LIMIT 20;

执行效率:type类型为range

执行时间:0.034s

执行下一页:获取上一页最后一个id值和score值

sql

体验AI代码助手

代码解读

复制代码

SELECT id, name, score from student
WHERE id < 4975166 AND score <= 99.9
ORDER BY score DESC LIMIT 20;

7. 总结

  1. 浅分页可以给order by字段添加索引
  2. 深分页可以给order by和select字段添加联合索引
  3. 通过手动回表,走联合索引
  4. 从业务方面思考,获取对应数据


转载来源:https://juejin.cn/post/7214735181172572219

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
23天前
|
存储 关系型数据库 MySQL
使用命令行cmd查询MySQL表结构信息技巧分享。
掌握了这些命令和技巧,您就能快速并有效地从命令行中查询MySQL表的结构信息,进而支持数据库维护、架构审查和优化等工作。
150 9
|
24天前
|
存储 关系型数据库 MySQL
在CentOS 8.x上安装Percona Xtrabackup工具备份MySQL数据步骤。
以上就是在CentOS8.x上通过Perconaxtabbackup工具对Mysql进行高效率、高可靠性、无锁定影响地实现在线快速全量及增加式数据库资料保存与恢复流程。通过以上流程可以有效地将Mysql相关资料按需求完成定期或不定期地保存与灾难恢复需求。
116 10
|
2月前
|
SQL 存储 缓存
MySQL 如何高效可靠处理持久化数据
本文详细解析了 MySQL 的 SQL 执行流程、crash-safe 机制及性能优化策略。内容涵盖连接器、分析器、优化器、执行器与存储引擎的工作原理,深入探讨 redolog 与 binlog 的两阶段提交机制,并分析日志策略、组提交、脏页刷盘等关键性能优化手段,帮助提升数据库稳定性与执行效率。
|
3月前
|
关系型数据库 MySQL 数据库
MySQL报错:未知系统变量'tx_isolation'及隔离级别查询
记住,选择合适的隔离级别,就像是在风平浪静的湖面上找到适合的划船速度——既要快到能赶上午饭(性能),又不至于翻船(数据一致性问题)。
185 3
|
3月前
|
SQL 关系型数据库 MySQL
MySQL 进行 select 查询时 where 条件中 in 的value数过多却导致无记录返回
MySQL 进行 select 查询时 where 条件中 in 的value数过多返回不符合预期怎么办?会不会遇到bug了?
197 0
|
5月前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
265 28
|
4月前
|
缓存 JSON 关系型数据库
MySQL 查询优化分析 - 常用分析方法
本文介绍了MySQL查询优化分析的常用方法EXPLAIN、Optimizer Trace、Profiling和常用监控指标。
|
4月前
|
存储 SQL 缓存
mysql数据引擎有哪些
MySQL 提供了多种存储引擎,每种引擎都有其独特的特点和适用场景。以下是一些常见的 MySQL 存储引擎及其特点:
131 0
|
6月前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为&#39;0&#39;或&#39;1&#39;,查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。

推荐镜像

更多