explain中extra出现using filesort即表示未走索引排序,是数据量过万就明显卡顿的硬伤;需紧盯extra和key两列,确保索引被选用且排序字段严格匹配最左前缀、顺序与方向一致。

ORDER BY 出现 Using filesort 就代表没走索引排序,这不是“有点慢”,是数据量一上万就卡死的信号。
怎么看是不是真没走索引排序
别猜,直接 EXPLAIN。盯死两列:
-
Extra出现Using filesort→ 没走索引排序,正在额外排序 -
key是NULL或没显示你建的索引名 → 索引压根没被选中
注意:type = index 不等于排序优化成功——它只是全索引扫描,如果 Extra 还有 Using where 或没 Using index,说明仍要回表,排序优势已打折扣。
为什么建了索引还是 Using filesort
常见但容易被忽略的硬伤:
-
WHERE和ORDER BY字段不在同一个联合索引里,比如只在status上建单列索引,却写WHERE status = 1 ORDER BY created_at - 联合索引顺序错:索引是
(created_at, status),但查询是WHERE status = 1 ORDER BY created_at——status不是最左前缀,索引直接被跳过 - MySQL 5.7 及更早版本会忽略
DESC声明,建INDEX (status, created_at DESC)实际按升序存;若查询强制ORDER BY created_at DESC,仍可能触发Using filesort - 字段隐式转换:比如索引是
VARCHAR(255),但ORDER BY用了VARCHAR(100)表达式,或字符集不一致(utf8mb4vsutf8)
怎么建才真正管用的联合索引
核心就一条:等值条件字段放最左,排序字段紧贴其后,方向严格一致。
- 查询是
SELECT id, name FROM users WHERE status = 1 AND type = 'vip' ORDER BY created_at DESC→ 建INDEX idx_status_type_created (status, type, created_at DESC) - 如果有范围条件(如
WHERE status = 1 AND created_at > '2026-01-01'),那ORDER BY只能跟在created_at后面的字段才有效,再后面的列无法参与排序 - 想覆盖查询字段减少回表?把常用
SELECT列加到索引末尾,比如(status, created_at DESC, name, email),但注意 TEXT/BLOB 字段会让整个索引失效
LIMIT 分页 + ORDER BY 的隐形陷阱
不是索引问题,但常被误判为“索引没用”:
-
ORDER BY created_at DESC LIMIT 10000, 20会强制 MySQL 扫描并排序前 10020 行,哪怕走了索引,I/O 和 CPU 成本也线性上涨 - 解决方案不是调索引,而是换分页逻辑:用游标(cursor-based pagination),记录上一页最后一条的
created_at和id,下一页查WHERE created_at -
SELECT *在这种场景下尤其危险——大字段越多,每行越重,排序内存开销越大
最易被忽略的一点:JOIN 后的 ORDER BY,即使驱动表走了索引,被驱动表的排序字段若未包含在联合索引中,优化器大概率放弃索引,直接 Using filesort。











