Using filesort一定慢,因MySQL无法用索引顺序返回结果而需额外排序;根本原因是ORDER BY字段未落在索引连续最左前缀上,或含函数/表达式、WHERE截断索引、混用ASC/DESC等。

ORDER BY 为什么突然变慢?先看执行计划里的 Using filesort
只要 EXPLAIN 输出的 Extra 列出现 Using filesort,就说明 MySQL 没法直接用索引顺序返回结果,得额外排序——这是性能拐点。不是“可能慢”,是“一定慢”,尤其数据量上万后,磁盘临时文件或内存排序开销会陡增。
根本原因:查询字段和 ORDER BY 字段没落在同一个索引的最左前缀上,或者用了不支持索引排序的表达式(比如 ORDER BY ABS(id))。
- 检查
ORDER BY字段是否为索引的**连续最左前缀**(例如索引是(a, b, c),那么ORDER BY a, b可以,ORDER BY b, c不行) - 确认
WHERE条件没“截断”索引:如果索引是(status, created_at),但查询写成WHERE status IN ('A','B') ORDER BY created_at,MySQL 通常无法用索引排created_at - 避免在
ORDER BY中对字段做函数或计算:ORDER BY UPPER(name)、ORDER BY updated_at + INTERVAL 1 DAY都会强制 filesort
什么样的索引能真正消除 Using filesort?
不是“有索引就行”,而是索引结构必须覆盖 WHERE 过滤 + ORDER BY 排序 + (可选)SELECT 返回字段的组合需求。重点看三个条件是否同时满足:
-
WHERE条件字段必须是索引的最左连续部分(如索引(shop_id, status, created_at),WHERE shop_id = 123 AND status = 'paid'合理;WHERE status = 'paid'就不行) -
ORDER BY字段必须紧接在WHERE字段之后,且方向一致(ORDER BY shop_id, status, created_at或全DESC;混用ASC/DESC在 MySQL 8.0 前基本无效) - 如果查询含
SELECT *或非索引字段,虽然排序能走索引,但回表成本仍高;尽量用覆盖索引,比如把常用返回字段加到索引末尾:(shop_id, status, created_at, order_no, amount)
示例:想查某店铺最近 10 笔已支付订单,按创建时间倒序
SELECT order_no, amount FROM orders WHERE shop_id = 1001 AND status = 'paid' ORDER BY created_at DESC LIMIT 10;
对应最优索引:INDEX (shop_id, status, created_at) —— 三者顺序不能错,created_at 必须放最后。
ORDER BY ... LIMIT 场景下,索引失效的典型陷阱
很多人以为加了 LIMIT 就“只取前 N 条”,MySQL 会聪明地少排序。其实不会:除非索引能完全支撑排序,否则它仍要扫全量匹配行再排序取 top-N,LIMIT 只是最后裁剪,不减少排序开销。
- 常见翻车点:
WHERE a = ? ORDER BY b DESC LIMIT 10,但索引只有(a)或(b)单列——必然Using filesort - 复合索引中,如果
WHERE用了范围条件(<,BETWEEN,LIKE 'abc%'),后续字段就无法用于排序。例如索引(a, b, c),WHERE a = 1 AND b > 10 ORDER BY c中,c无法利用索引排序 - 注意隐式类型转换:如果
user_id是字符串类型,但查询写成WHERE user_id = 123(传整数),可能导致索引失效,连带让后续ORDER BY失效
验证和调试:别信感觉,用 EXPLAIN FORMAT=TREE 看真实路径
MySQL 8.0+ 的 FORMAT=TREE 能清晰显示是否用了索引排序,比传统 EXPLAIN 更准。关键看输出里有没有 ordering operation 和 using_filesort: false。
- 老版本用
EXPLAIN后紧盯type(最好为ref或const)、key(是否命中预期索引)、Extra(确认无Using filesort) - 用
SHOW STATUS LIKE 'Sort%'对比前后:优化后Sort_merge_passes和Sort_rows应明显下降 - 真实慢查日志里找
Query_time高但Rows_examined低的语句——大概率是ORDER BY导致的 filesort 主导了耗时
索引排序能力很“娇气”:字段顺序、等值/范围条件位置、ASC/DESC 一致性、甚至字符集校对规则,任何一个细节偏移,就退回 filesort。与其猜,不如每次改完立刻 EXPLAIN 看一眼。










