降序索引是什么
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 会按真实降序处理。如果原查询是按升序设计的,方向写反反而制造新的排序开销,升级前应逐条核对混合排序场景。