降序索引解决什么
MySQL 8.0 起支持真正的降序索引:建索引时可以写「a ASC, b DESC」这样的混合方向,让多列混合排序直接被索引满足,省掉额外排序步骤。8.0 之前 DESC 关键字会被解析但忽略,混合方向排序只能靠额外排序完成。
基本信息
| 适用版本 | MySQL 8.0+ |
|---|---|
| 语法 | 索引定义里写 ASC / DESC,例如 (a ASC, b DESC) |
| 单列降序 | 更早版本也能通过反向扫描索引实现 |
| 真正需要降序索引 | 多列排序方向不一致的场景 |
| 验证方式 | EXPLAIN 里确认没有额外排序步骤 |
典型使用场景
- 列表页按「创建时间倒序加 ID 正序」排序
- 排行榜按分数降序、并列时按时间正序
- 多维度混合排序的报表
- 排查 ORDER BY 引起的排序开销
- 索引设计评审时确认排序方向是否匹配
示例
示例
-- 混合方向的降序索引
ALTER TABLE events
ADD INDEX idx_a_asc_b_desc (a ASC, b DESC);
-- 排序方向与索引一致,可直接借用索引顺序
SELECT * FROM events ORDER BY a ASC, b DESC LIMIT 20;
-- 方向不一致时会退化成额外排序
SELECT * FROM events ORDER BY a ASC, b ASC LIMIT 20;
-- 用 EXPLAIN 确认没有额外排序
EXPLAIN SELECT * FROM events ORDER BY a ASC, b DESC LIMIT 20;索引方向与排序
| 索引定义 | 排序写法 | 能否直接用索引 |
|---|---|---|
| (a ASC, b DESC) | ORDER BY a ASC, b DESC | 可以 |
| (a ASC, b DESC) | ORDER BY a ASC, b ASC | 不能,需额外排序 |
| (a DESC) | ORDER BY a DESC | 可以 |
| (a ASC) | ORDER BY a DESC | 可以(反向扫描) |
| (a ASC, b ASC) | ORDER BY a DESC, b DESC | 可以(整体反向扫描) |
单列降序通常不需要降序索引:优化器可以反向扫描普通索引。降序索引真正解决的是多列排序方向不一致,或正反混合扫描无法满足的顺序。
旧版本上写 DESC 不会报错但也不生效:5.7 及更早版本会忽略这个关键字,实际索引方向与预期不一致,升级或评审时要留意。
降序索引不影响自身维护开销,但为每个排序组合都加索引会明显拖慢写入:先确认排序模式是否稳定,再决定加几条。
分页查询最容易暴露排序问题:排序方向与索引对齐之后,翻页时的排序开销与深分页代价通常也会一起下降。