using filesort 是 mysql 无法利用索引有序性完成排序的明确信号,表明必须额外启动内存或磁盘排序;根本原因包括 where 条件破坏索引连续性(如范围查询、非最左匹配)、order by 含函数或升降序不一致、索引字段顺序未严格匹配查询路径。

Using filesort 不是警告,是排序已脱离索引的明确信号——只要 EXPLAIN 的 Extra 列里出现它,就代表 MySQL 没法按索引物理顺序读出结果,必须额外启动一次内存或磁盘排序。查几千行可能不明显,查 10 万行基本卡死。
WHERE 条件破坏了索引的连续有序性
MySQL 只能靠单个 B+ 树索引一次性完成「定位 + 有序读取」,一旦 WHERE 中用了范围条件、跳过字段或非最左匹配,后续字段就失去局部有序性。
-
WHERE a > 10 ORDER BY b:索引(a, b)无法用于排序,因为a > 10扫描出的b值在物理上不连续 -
WHERE b = 1 ORDER BY c:索引(a, b, c)无法生效,b不是最左字段,索引无法高效定位起始位置 -
WHERE a = 1 ORDER BY c:跳过中间字段b,索引(a, b, c)对c单独排序无效
ORDER BY 含函数、表达式或方向不一致
索引存储的是原始字段值,不是计算结果;而升降序混合在老版本中根本不可用。
-
ORDER BY UPPER(name)或ORDER BY created_at + INTERVAL 1 DAY:索引值 ≠ 表达式结果,直接失效 -
ORDER BY user_id ASC, created_at DESC配索引(user_id, created_at):MySQL 5.7 及以前完全不认混合方向,建了DESC也白建 - MySQL 8.0+ 支持
CREATE INDEX idx ON t(a, b DESC),但优化器是否选用仍取决于统计信息和查询结构
索引字段顺序没对齐查询执行路径
不是“把所有涉及字段塞进索引就行”,而是必须严格按「等值过滤字段 → 范围过滤字段(慎用)→ 排序字段」的物理顺序组织。
- 查询
WHERE status = 1 AND city = 'Beijing' ORDER BY create_time DESC,索引应为(status, city, create_time DESC),而非(create_time, status)或(city, status, create_time) - 哪怕所有字段都在索引里,如果
ORDER BY字段不在最右连续段(如索引(a, b, c)却写ORDER BY a, c),依然触发Using filesort - 覆盖索引(如加
id, name)能减少回表,但不能消除Using filesort——排序有效性优先级高于返回字段优化
最容易被忽略的一点:即使 key 显示用了索引,Extra 里仍有 Using filesort,说明索引只服务了 WHERE,没服务 ORDER BY。此时别急着加字段,先确认 ANALYZE TABLE 是否执行过——优化器可能因统计信息过期而误判索引价值。











