能,但仅当ORDER BY方向与降序索引定义逐列严格一致、WHERE满足最左前缀且无函数表达式时才跳过FileSort;需通过EXPLAIN的Extra字段(无Using filesort)、key命中及rows显著减少来验证。

MySQL 8.0 的降序索引(Descending Index)不是“自动加速所有 DESC 查询”的银弹,它只在 ORDER BY 子句与索引定义方向逐列严格一致时才跳过 FileSort。
降序索引生效的硬性条件
建了 INDEX (a DESC, b DESC),不代表 ORDER BY a DESC, b ASC 或 ORDER BY a DESC 单独就能用上——必须完全匹配。
- 索引定义和
ORDER BY的列顺序、排序方向必须一模一样,不能跳过中间列,也不能方向错位 - WHERE 中的等值条件必须构成索引最左前缀:比如索引是
(status, created_at DESC),那WHERE status = 'done'才能利用后续的created_at DESC排序;若只写WHERE user_id = 123,这个索引就完全无效 - 含函数或表达式的
ORDER BY(如ORDER BY DATE(created_at) DESC)永远无法命中任何普通索引,包括降序索引
怎么确认降序索引真正在工作
光看 EXPLAIN 的 key 字段不够,关键看 Extra 和 rows。
- 如果
Extra出现Using filesort,说明没走成索引排序,无论你建了多少个 DESC 索引 - 如果
type是range或ref,且rows明显小于表总行数,基本可确认走了索引扫描而非全表+排序 - MySQL 8.0.20+ 可用
EXPLAIN FORMAT=TREE,直接看到执行计划里有没有filesort节点
降序索引的隐性成本和常见误用
它不是免费午餐,空间和维护成本都得算进去。
- 降序索引在 InnoDB 中实际存储为反向键值(比如字符串按字节逆序编码),和对应升序索引物理上不兼容,
INDEX (a ASC)和INDEX (a DESC)必须各建一个,空间翻倍 - 主键中用
DESC要小心:8.0.11 及更早版本会直接忽略,8.0.12+ 才真正支持 - 很多人先建了个
INDEX (c1 DESC),再加WHERE c1 > 100就以为能又过滤又排序——其实不行,B+ 树对单列降序索引做范围扫描时,方向和排序逻辑冲突,往往退化为全索引扫描
比建降序索引更优先该做的事
多数 “需要倒序”的慢查询,根源不在排序本身,而在索引设计或查询写法。
- 先检查是否漏掉了高选择性的等值 WHERE 条件:比如
WHERE status = 'active' ORDER BY updated_at DESC,应该建INDEX (status, updated_at DESC),而不是只给updated_at建单列降序索引 - 确认没有隐式类型转换:
WHERE id = '123'(id 是 INT)会强制全表扫描,再好的降序索引也救不了 - 用
sys.schema_unused_indexes查查已有索引里哪些根本没人用,别一边建新索引一边养着一堆僵尸索引
降序索引真正的价值场景很窄:高频、高过滤性、固定列序+固定方向的排序查询。其他时候,先调 prefer_ordering_index=off、加覆盖字段、拆分大字段,往往比硬上 DESC 索引更见效。



















