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
儲存引擎,且有下列限制如果次要索引包含遞減索引金鑰資料行,或者如果主鍵包含遞減索引資料行,則不支援變更緩衝。
InnoDB
SQL 剖析器不使用遞減索引。對於InnoDB
全文搜尋,這表示索引資料表的FTS_DOC_ID
資料行上所需的索引無法定義為遞減索引。如需詳細資訊,請參閱 第 17.6.2.4 節「InnoDB 全文索引」。
遞減索引適用於所有可使用遞增索引的資料類型。
遞減索引適用於一般 (未產生) 和產生資料行 (包括
VIRTUAL
和STORED
)。DISTINCT
可以使用任何包含相符資料行的索引,包括遞減金鑰部分。遞減索引適用於
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)
來表示,如下所示
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 額外資訊。