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 子句执行正向索引扫描,不需要使用 filesort 操作:
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存储引擎,以下是限制:-
更改缓冲区不支持辅助索引,如果索引包含降序索引键列或主键包含降序索引列。
-
InnoDBSQL 解析器不使用降序索引。对于InnoDB全文搜索,这意味着索引表的FTS_DOC_ID列上的索引不能定义为降序索引。更多信息,请参阅 第 17.6.2.4 节,“InnoDB 全文索引”。
-
-
降序索引支持所有数据类型,其中升序索引可用。
-
降序索引支持普通(非生成)和生成列(包括
VIRTUAL和STORED)。 -
DISTINCT可以使用任何包含匹配列的索引,包括降序键部分。 -
降序索引支持
BTREE但不支持HASH索引。降序索引不支持FULLTEXT或SPATIAL索引。明确指定的
ASC和DESC设计符对于HASH、FULLTEXT和SPATIAL索引将导致错误。
您可以在 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) 后缀形式显示,例如:
mysql> EXPLAIN FORMAT=TREE SELECT * FROM t1 ORDER BY a ASC\G
*************************** 1. row ***************************
EXPLAIN: -> Index scan on t1 using a_desc_b_asc (reverse) (cost=0.35 rows=1)
另请参阅 EXPLAIN 额外信息。