首页/数据/数据库速查/降序索引(Descending Index,8.0)
性能与调优57 条

降序索引(Descending Index,8.0)

8.0 真正支持 DESC 语义的索引:混合排序(a ASC, b DESC)场景下消除 filesort;5.7 的 DESC 只是语法糖实际仍升序存储。

数据库速查数据更新于 2026-10-13

降序索引是什么

MySQL 8.0 才真正支持降序索引:索引可以按 (a ASC, b DESC) 这样的混合顺序存储,让「一列升序一列降序」的 ORDER BY 直接用索引顺序扫描,省掉 filesort。5.7 及更早版本里 DESC 只是写法的语法糖,实际仍按升序存储。这意味着同一份 DDL 在升级后行为会发生变化,迁移评估时不能忽略这一点。

基本信息

版本差异8.0 真实按降序存储;5.7 及更早忽略 DESC 语义
创建语法ADD INDEX 索引名 (a ASC, b DESC)
适用场景混合升降序的排序需求
验证方式EXPLAIN 的 Extra 中不再出现 Using filesort
迁移注意升级后索引结构不同,必要时重建以匹配查询

典型使用场景

  • 排行榜分页:主键升序、时间降序的混合排序,用降序索引消除 filesort
  • 时间线查询:按状态升序、创建时间降序取最新记录
  • 统计报表:多维排序中升降序混用的场景
  • 升级评估:核对 5.7 时代建表的 DDL 中 DESC 关键字在 8.0 下的实际效果
  • 性能回归排查:升级后部分查询变慢时,检查索引存储方向与查询方向是否匹配

创建与验证

创建与验证
-- 混合方向索引:a 升序、b 降序
ALTER TABLE appdb.metrics ADD INDEX idx_a_b (a ASC, b DESC);
-- 查询的排序方向要与索引方向一致才可能省掉排序
EXPLAIN SELECT id, a, b FROM appdb.metrics
ORDER BY a ASC, b DESC LIMIT 100;
-- Extra 列不再出现 Using filesort 即说明索引生效
SHOW INDEX FROM appdb.metrics WHERE Key_name = 'idx_a_b';
-- Collation 列显示 A 或 D,对应升序与降序

注意事项对照

情形是否需要降序索引说明
纯升序排序不需要B+ 树可反向扫描满足降序需求
纯降序排序通常不需要反向扫描即可,混合方向才需要
混合升降序需要否则必然 filesort
仅等值查询不需要索引方向不影响等值匹配
纯升序或纯降序的排序不需要降序索引:B+ 树可以反向扫描,优化器本身就能满足,额外建降序索引只会增加维护成本。
升级到 8.0 后,5.7 时代 DDL 里的 DESC 会按真实降序处理。如果原查询是按升序设计的,方向写反反而制造新的排序开销,升级前应逐条核对混合排序场景。

易错点

  • 沿用 5.7 的直觉给所有排序列都加 DESC:8.0 会真实建成降序索引,方向与查询不匹配时反而出现新的 filesort
  • 低版本导出的 DDL 里 DESC 被静默忽略:升级后索引行为变化,性能出现回归且不易定位
  • 以为降序索引能优化所有排序:纯单向排序本就可以反向扫描,额外索引只是增加写入成本
  • 建完不验证:只看建表成功,没有用 EXPLAIN 确认 filesort 是否消除
  • 在评价优化效果时忽略 LIMIT:带 LIMIT 的排序查询才最受益于索引顺序,去掉 LIMIT 后仍可能全量排序

数据来源与参考

  • MySQL 8.0 Reference Manual: Descending Indexes

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌