能跳过using filesort,但仅当where最左列等值匹配、order by方向与索引逐列严格一致、select列被索引覆盖三者同时满足;缺一不可。

能,但只在三个条件同时满足时才真正跳过 Using filesort:WHERE 最左列是等值匹配、ORDER BY 方向与索引逐列严格一致、SELECT 列被索引覆盖。缺一不可,否则建了也白建。
CREATE INDEX 里写 DESC 到底有没有用
只对 MySQL 8.0.12+ 的 InnoDB 表生效;8.0.11 及更早版本会静默忽略,建出来的仍是升序索引。
- 验证是否生效:
SHOW CREATE TABLE table_name输出中必须明确出现a DESC,而不是只写a - 查系统表更准:
SELECT COLLATION FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_NAME = 't' AND INDEX_NAME = 'idx',结果为D才代表降序存储已落地 - 主键中写
DESC在 8.0.12+ 才被接受;8.0.11 及以前直接报错或强制转为 ASC
ORDER BY a DESC, b ASC 必须配对应方向的联合索引
MySQL 8.0 支持每列独立指定方向,但方向组合必须和 ORDER BY 逐列完全一致——少一个 ASC、多一个 DESC 都不匹配。
- 要优化
ORDER BY user_id DESC, created_at ASC,必须建INDEX (user_id DESC, created_at ASC) -
INDEX (user_id DESC, created_at DESC)对ORDER BY user_id DESC, created_at ASC完全无效 -
INDEX (user_id ASC, created_at DESC)同样不匹配,因为首列方向已错 - 方向不一致不是“部分生效”,而是整个排序逻辑无法下推,必然触发
Using filesort
为什么 key 字段命中了,却还是 Using filesort
key 字段只说明用了哪个索引做数据查找,不保证排序复用。关键看 Extra 字段:
- 出现
Using filesort→ 排序没走索引,哪怕key显示命中了带DESC的索引 - 没出现
Using filesort,且type是ref或range,rows远小于总行数 → 基本确认排序已下推到索引扫描层 - MySQL 8.0.20+ 可用
EXPLAIN FORMAT=TREE,直接看执行计划里有没有filesort节点 - 单列降序索引 +
WHERE updated_at > '2025-01-01'这种范围条件,几乎必然退化为全索引扫描,物理顺序和扫描方向冲突
最容易被忽略的坑:单列降序索引 + 范围查询基本无效
这是最常踩的坑:建了 INDEX (updated_at DESC),又写 WHERE updated_at > '2025-01-01' ORDER BY updated_at DESC,以为能又过滤又排序——实际 B+ 树对单列降序索引做范围扫描时,物理存储顺序和扫描方向冲突,往往退化为全索引扫描。
- 真正有效的做法是补一个高选择性等值条件,例如:
WHERE status = 'done' AND updated_at > '2025-01-01' ORDER BY updated_at DESC,再配联合索引(status, updated_at DESC) - 降序索引不是给单字段倒排准备的,它是为「等值过滤 + 精确方向排序」这个组合服务的
- 单独建
DESC索引,90% 的场景都浪费空间还拖慢写入;InnoDB 中它和对应ASC索引是两套独立物理结构,无法复用
NULL 值在 DESC 索引中默认排最前面(因为 MySQL 把 NULL 视为最小值),和 ASC 索引相反,容易导致业务语义偏差,这点很少人注意。











