Using filesort说明排序未走索引,需额外内存或磁盘排序;根源在于WHERE与ORDER BY字段未按最左前缀匹配复合索引,如WHERE status=1 ORDER BY created_at DESC需建INDEX(status, created_at),而非单列或顺序颠倒索引。

EXPLAIN里出现Using filesort说明排序没走索引
它不是错误,但代表MySQL必须把满足WHERE条件的行全捞出来,再额外做一次内存或磁盘排序——哪怕只查10条,也可能扫描几万行后才排序。常见于ORDER BY字段没被索引覆盖、或索引结构和查询模式不匹配。
复合索引必须按「WHERE等值字段 + ORDER BY字段」严格顺序创建
比如查询是:SELECT id, name FROM users WHERE status = 1 ORDER BY created_at DESC,正确索引是INDEX (status, created_at),而不是(created_at, status)或单列(created_at)。
- 如果
WHERE含范围条件(如created_at > '2023-01-01'),那它之后的字段就不能用于排序优化 -
ORDER BY a ASC, b DESC在MySQL 8.0+才能用INDEX (a ASC, b DESC)支持;5.7及以前只能全ASC或全DESC - 索引
(status, created_at, id)比(status, created_at)多占空间,除非你SELECT id且想避免回表
索引存在 ≠ 被选用:检查used_key_parts和统计信息
执行EXPLAIN FORMAT=JSON看used_key_parts是否包含排序字段,同时using_filesort为true,说明索引被用了但没覆盖排序逻辑。
- 运行
ANALYZE TABLE users更新统计信息,避免优化器因行数误判而弃用索引 - 用
SELECT ... FROM users USE INDEX (idx_status_created) ...强制指定索引,验证是否真能消除Using filesort - 注意
!=、IS NULL、函数包裹字段(如ORDER BY YEAR(created_at))都会让索引失效
覆盖索引能进一步去掉“Using where”后的回表开销
当SELECT字段全在索引里,执行计划会显示Using index,比只消除Using filesort更省IO。但优先级一定是先保排序走索引,再考虑覆盖。
- 原查询
SELECT * FROM orders WHERE company_code = 'TENCENT' ORDER BY create_time DESC→ 改成SELECT company_code, create_time, order_id+ 索引(company_code, create_time, order_id) - 别为了覆盖而堆砌冗余字段,
id主键通常已隐式包含在二级索引中(InnoDB),不必重复加 -
Using index和Using filesort不会同时出现;前者意味着排序+取值全在索引B+树上完成
实际中最容易被忽略的是:WHERE里的非等值条件会截断索引排序能力,以及优化器可能因统计不准跳过你刚建的索引——得用FORMAT=JSON确认它到底有没有真正用上排序字段。


















