using filesort不是错误,而是mysql放弃索引排序、改用内存或磁盘额外排序的信号;它通常因order by字段未命中联合索引最左前缀、被范围条件截断、含函数表达式或select未覆盖索引字段所致,需结合explain的extra和key列、rows_examined与rows_sent比值及sort_merge_passes综合判断是否需优化。

为什么MySQL慢日志里总出现 Using filesort?
这不代表真在磁盘上排序,而是MySQL优化器决定不走索引完成ORDER BY或GROUP BY,改用内存(或临时文件)做排序。它本身不是错误,但通常是性能瓶颈的信号——尤其当Rows_examined远大于Rows_sent时。
怎么确认是哪个SQL触发了 Using filesort?
别只盯着慢日志里的Query_time,重点看三处:
- 日志中是否包含
Rows_examined: 123456和Rows_sent: 20这种严重不匹配——说明扫描大量行只返回少量结果,排序代价高 - 是否有
Sort_merge_passes: 5(在SHOW GLOBAL STATUS LIKE 'Sort%'里查),值>0说明已溢出内存,开始用磁盘合并排序 - 用
EXPLAIN FORMAT=TREE(MySQL 8.0+)或EXPLAIN看执行计划,确认Extra列是否含Using filesort,且key列为NULL或未覆盖ORDER BY字段
怎样让MySQL避免 Using filesort?
核心思路:让排序能走索引,而不是回表后二次排序。常见有效做法:
- 把
ORDER BY字段加进联合索引最右侧,例如SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC,建索引INDEX (user_id, created_at) - 如果
WHERE和ORDER BY字段不同,优先保证WHERE条件的索引前缀高效,再把ORDER BY字段追加到索引末尾;不要反过来,否则WHERE可能失效 - 避免在
ORDER BY字段上用函数或表达式,如ORDER BY UPPER(name)会强制filesort;需要的话,建函数索引(MySQL 8.0+):CREATE INDEX idx_name_upper ON t1 ((UPPER(name))) -
SELECT *容易引发filesort,因为索引通常不包含所有列;改用具体字段,并确保这些字段都在索引中(覆盖索引)
filesort 一定得优化吗?
不一定。小结果集(Rows_sent )、内存充足(<code>sort_buffer_size够大)、且Sort_merge_passes = 0时,filesort开销可忽略。真正要盯的是:Rows_examined / Rows_sent > 100 + Sort_merge_passes > 0 + 单次查询耗时突增。这时候才值得调索引或重写查询——否则可能白忙活。











