【MySQL】orderby/groupby出现Using filesort根因分析及优化

在日常的数据库运维中,我们可能会遇到一些看似难以理解的现象。比如两个SQL查询语句,仅仅在ORDER BY子句上略有不同,却造成了性能的天壤之别------一个飞速完成,一个则让数据库崩溃。今天就让我们围绕这个问题,深入剖析MySQL的查询优化机制。

Q1 - 能否自我介绍下?

嗨,大家好,我是********小 明******** (小明java问道之路) 互联网大厂后端研发专家,2022博客之星TOP3/博客专家/CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网5万粉丝博主。

一个8年开发经验的老兵,专注于面试/后端/源码/架构/算法,擅长面试高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。

Q2 - 出现 Using filesort问题分析?

  • 我们拿到两条SQL语句,第一条查询语句是:"WHERE time >= '2023-12-21 00:00:00' ORDER BY time ASC"
  • 第二条查询语句是:"WHERE time >= '2023-12-21 00:00:00' ORDER BY id ASC"。

通过EXPLAIN命令对两条SQL进行分析后发现,在使用id作为排序字段时,MySQL使用了Using filesort 操作;但是在使用time作为排序字段时,却没有 Using filesort 。而我们知道,Using filesort通常代表着磁盘排序,相较于内存排序,它的性能开销要大很多。

那么问题来了,既然id是主键,应该有更好的性能,为什么会导致 Using filesort的出现呢?

**Q3 -**问题原因是什么?

在我们的例子中,假设time字段的值是递增的,并且与id的增长趋势大致一致。那么在执行类似"WHERE time >='2023-12-21 00:00:00' ORDER BY time ASC"的查询时,MySQL可以通过time索引找到满足条件的第一个记录,然后顺序扫描后面的记录直到没有满足WHERE条件的记录为止。

在这个过程中,由于已经按照time字段的顺序读取记录,所以不需要额外的排序操作

但当我们改为"WHERE time >='2023-12-21 00:00:00' ORDER BY idASC"时,就不能保证按id的顺序读取记录了。

因为虽然两个字段都是递增的,但并不能确保每个time值对应的id也是按顺序排列的 。此时,MySQL查询优化器可能会选择扫描所有满足条件的记录,并把它们加载进入一个临时表进行排序,这样就产生了 Using filesort

Q4 - MySQL索引与查询优化器?

MySQL的索引可以提高查询速度,因为它们使得MySQL可以找到记录而无需扫描整个表。然而,索引并非万能的,它也会带来存储和管理的开销。所以,当MySQL选择执行计划时,会基于众多因素来考虑是否使用索引、使用哪种索引,以及如何使用索引。

NULL值和数据分布及唯一性都可以影响MySQL索引的使用效果。除此之外,MySQL的查询优化器还会根据查询条件和排序规则,选择最佳的索引进行操作。这就可能出现我们现在这个情况,即使id是主键,但如果在使用id进行排序时,不能有效利用索引,也可能产生 Using filesort操作。

**Q5 -**解决方案是什么?

  • 如果我们经常需要按照time和id排序的查询,一种解决方案是创建联合索引(time, id)。这样即使按照id排序,也能利用索引进行优化。因为对于联合索引来说,MySQL可以在满足time过滤条件的情况下,直接使用索引进行id的排序。
  • 可以尝试调整MySQL的sort_buffer_size参数。如果排序的数据量小于这个参数,那么MySQL可能会选择内存排序而非 Using filesort。需要注意的是,这个参数是每个连接独享的,设置得过大可能会浪费内存资源。

总结

理解MySQL索引的使用规则和查询优化器的工作原理,可以帮助我们更好地优化数据库性能,解决实际问题。同时,要明白没有最好的索引,只有最合适的索引。我们需要根据业务需求和实际数据分布,来选择和优化索引。

在本次的问题中,我们通过理解索引、排序以及查询优化器的工作原理,找出了导致问题的根源,并提出了相应的解决方案。

充分体现了,深入理解和掌握相关知识,对于我们解决实际问题的重要性。

相关推荐
南客先生2 分钟前
MySQL索引优化、SQL分析与运行原理 - Java架构师面试实战
mysql·mvc·锁机制·sql分析·事务隔离级别·索引优化
欧先生^_^9 分钟前
Jinja 的详细介绍和学习方法
数据库·sqlite
husterlichf10 分钟前
MYSQL 常用字符串函数 和 时间函数详解
数据库·sql·mysql
hnlucky35 分钟前
redis 数据类型新手练习系列——Hash类型
数据库·redis·学习·哈希算法
LucianaiB1 小时前
【金仓数据库征文】_AI 赋能数据库运维:金仓KES的智能化未来
运维·数据库·人工智能·金仓数据库 2025 征文·数据库平替用金仓
时序数据说2 小时前
时序数据库IoTDB在航空航天领域的解决方案
大数据·数据库·时序数据库·iotdb
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
AnsenZhu2 小时前
2025年Redis分片存储性能优化指南
数据库·redis·性能优化·分片
Johny_Zhao2 小时前
MySQL 高可用集群搭建部署
linux·人工智能·mysql·信息安全·云计算·shell·yum源·系统运维·itsm
oydcm2 小时前
MySQL数据库概述
数据库·mysql