MySQL EXPLAIN 中 Using filesort 怎样判断是否需要优化
来源:17golang原创
时间:2026-10-23 04:04:12 438浏览 收藏
MySQL 的 EXPLAIN 里看到 Extra: Using filesort,先不要急着把“filesort”理解成一定落盘。它真正表示的是:当前查询不能直接用索引提供 ORDER BY 的顺序,MySQL 需要增加一个排序阶段。小结果集、明确的 LIMIT 或低频后台查询可能完全可以接受;高频接口、排序前要处理大量行时,才值得优先优化。
官方地址:https://dev.mysql.com/doc/refman/8.4/en/order-by-optimization.html
判断是否需要优化,先看排序前要处理多少行、最终返回多少行以及请求频率,再看能否让索引同时服务过滤和排序。只看到 Using filesort 就加索引,容易换来更高写入成本,却没有解决真实瓶颈。
Using filesort 到底说明了什么
在传统格式的 EXPLAIN 中,Extra 出现 Using filesort,说明 MySQL 需要先按连接类型找到满足条件的行,再把排序键和行指针放入排序过程,最后按排序结果取回行。它不是“使用了某个名为 filesort 的文件”,也不直接告诉你排序一定使用磁盘。
MySQL 官方文档把 filesort 定义为额外排序阶段:如果结果集能放进排序缓冲区,排序可以在内存中完成;结果较大时才可能使用临时磁盘文件。因此第一步应该是把它当作“计划中的额外工作”来观察,而不是把标记本身当作故障结论。

用 rows、LIMIT 和频率判断排序成本
我会先把问题拆成“每次排序多少行”和“这条 SQL 多久发生一次”。例如下面的查询,即使 ORDER BY created_at DESC 无法走排序索引,如果过滤后只有几十行且 LIMIT 20,它的排序工作量可能很有限;反过来,过滤条件宽、LIMIT 很大或分页很深时,filesort 才更值得重点排查。
-- 先保留真实查询形状,重点观察 rows、key、Extra 和 LIMIT 的组合 EXPLAIN SELECT id, title, created_at FROM articles WHERE category_id = 12 AND status = 'published' ORDER BY created_at DESC LIMIT 20;
rows 是优化器估算的扫描行数,不是一次运行的精确耗时。判断时至少记录三组信息:过滤后估算行数、最终返回行数、这条 SQL 的调用频率。接口响应慢时,再用适合当前版本的实际执行分析或慢查询观测补充证据;不要把 EXPLAIN 的一个字段当成完整性能结论。
| 观察到的组合 | 优先判断 | 是否立即改索引 |
|---|---|---|
| rows 小、LIMIT 小、调用低频 | 额外排序可能是可接受成本 | 通常不急 |
| rows 大、LIMIT 小但高频 | 每次都在大量候选行中挑前几条 | 优先检查过滤与排序复合索引 |
| rows 大、LIMIT 深或无 LIMIT | 排序结果集本身就很大 | 先缩小结果范围或改变查询形状 |
| 同时出现 Using temporary | 可能还有中间结果物化 | 分开判断临时表与排序原因 |
检查 ORDER BY 能不能和过滤共用索引
索引优化的目标不是让 Extra 看起来更“干净”,而是减少需要扫描和排序的行。假设常用条件是固定的 category_id、status,结果按 created_at 倒序取前 20 条,可以评估让索引覆盖过滤列和排序列的组合:
-- 复合索引的列顺序要对应稳定的过滤条件和排序需求 CREATE INDEX idx_articles_category_status_created ON articles (category_id, status, created_at DESC); -- 建索引后重新查看 possible_keys、key、rows 与 Extra EXPLAIN SELECT id, title, created_at FROM articles WHERE category_id = 12 AND status = 'published' ORDER BY created_at DESC LIMIT 20;
这不是“看到 filesort 就必建此索引”的通用答案。还要检查查询是否真的稳定使用这组条件、字段选择性是否合适、索引是否增加了写入和存储成本,以及是否存在另一条更高频的查询在争用索引设计。若 ORDER BY 包含表达式、不同表的列、无法匹配的前缀,或排序方向与索引形状不适配,MySQL 仍可能保留 filesort。

不能消除 filesort 时,再看排序资源
有些查询天然需要排序,例如按计算表达式排序、需要从较大结果集中取前若干条,或者排序字段无法由可用索引直接提供。此时不要只靠盲目增大 sort_buffer_size。官方建议把它作为排序资源的一部分观察:排序缓冲按需增长;结果过大时可能使用临时磁盘文件;Sort_merge_passes 可以帮助观察临时文件合并次数。
-- 查看排序合并次数,比较同一类查询在调整前后的趋势 SHOW GLOBAL STATUS LIKE 'Sort_merge_passes'; -- 只在确认排序是主要成本后,按会话范围做谨慎实验 SET SESSION sort_buffer_size = 1048576;
如果临时目录空间或磁盘吞吐才是瓶颈,检查 tmpdir 的文件系统容量与并发影响;如果是深分页造成大量无效排序,优先考虑缩小时间范围、使用稳定游标条件或改写业务查询。参数调整只能改变排序资源,不能替代合理的过滤和索引。
可以把最终判断归纳成一条路径:先看 EXPLAIN 是否同时存在大量 rows 与较大的结果范围,再确认 ORDER BY 是否有机会与过滤共用索引,最后才观察排序缓冲、临时文件和合并次数。每次改动后只比较同一查询形状的计划与线上观测,避免把不同 SQL 的结果混在一起。
相关问题
Using filesort 是不是一定使用磁盘?
不是。它表示额外排序阶段;排序可能在内存中完成,结果较大时才可能使用临时磁盘文件。EXPLAIN 本身不区分内存 filesort,需结合优化器跟踪或运行观测判断。
把 ORDER BY 删掉能解决问题吗?
只有业务不要求顺序时才可以删。为了隐藏执行计划标记而改变结果语义,会把性能问题变成业务错误。
增大 sort_buffer_size 就能优化吗?
不一定。它只影响排序缓冲上限,不能减少候选行,也不能让无法匹配的 ORDER BY 自动变成索引排序;应先确认排序是主要成本。
-
374 收藏
-
499 收藏
-
384 收藏
-
184 收藏
-
265 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习