MySQL 8.0 降序索引
MySQL 支持降序索引:索引定义中的 DESC 不再被忽略,而是导致按降序存储键值。 以前,可以以相反的顺序扫描索引,但会降低性能。 按正向顺序扫描降序索引,这样效率更高。 当最有效的扫描顺序混合了某些列的升序和其他列的降序时,降序索引还使优化器可以使用多列索引。
考虑以下表定义,其中包含两列和四个两列索引定义,用于列上的升序和降序索引的各种组合:
CREATE TABLE t (
c1 INT, c2 INT,
INDEX idx1 (c1 ASC, c2 ASC),
INDEX idx2 (c1 ASC, c2 DESC),
INDEX idx3 (c1 DESC, c2 ASC),
INDEX idx4 (c1 DESC, c2 DESC)
);
表定义产生四个不同的索引。 优化器可以对每个 ORDER BY 子句执行正向索引扫描,并且不需要使用文件排序操作:
ORDER BY c1 ASC, c2 ASC -- optimizer can use idx1
ORDER BY c1 DESC, c2 DESC -- optimizer can use idx4
ORDER BY c1 ASC, c2 DESC -- optimizer can use idx2
ORDER BY c1 DESC, c2 ASC -- optimizer can use idx3
降序索引的使用受以下条件的约束:
- 只有 InnoDB 存储引擎支持降序索引,有以下限制:
- 如果索引包含降序索引键列或主键包含降序索引列,则二级索引不支持更改buffer。
- InnoDB SQL 解析器不使用降序索引。 对于 InnoDB 全文搜索,这意味着索引表的 FTS_DOC_ID 列上所需的索引不能定义为降序索引。
- 所有提供升序索引的数据类型都支持降序索引。
- 普通(非生成)列和生成列(VIRTUAL 和 STORED)支持降序索引。
- DISTINCT 可以使用任何包含匹配列的索引,包括降序键部分。
- 具有降序键部分的索引不用于调用聚合函数但没有 GROUP BY 子句的查询的 MIN()/MAX() 优化。
- BTREE 支持降序索引,但 HASH 索引不支持。 FULLTEXT 或 SPATIAL 索引不支持降序索引。
为 HASH、FULLTEXT 和 SPATIAL 索引显式指定 ASC 和 DESC 指示符会导致错误。
您可以在 EXPLAIN 输出的 Extra 列中看到优化器能够使用降序索引,如下所示:
mysql> CREATE TABLE t1 (
-> a INT,
-> b INT,
-> INDEX a_desc_b_asc (a DESC, b ASC)
-> );
mysql> EXPLAIN SELECT * FROM t1 ORDER BY a ASC\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: index
possible_keys: NULL
key: a_desc_b_asc
key_len: 10
ref: NULL
rows: 1
filtered: 100.00
Extra: Backward index scan; Using index
在 EXPLAIN FORMAT=TREE 输出中,使用降序索引是通过在索引名称后面添加( reverse)来指示的在 EXPLAIN FORMAT=TREE 输出中,使用降序索引是通过在索引名称后面添加( reverse)来指示的