MySQL 支援隱形索引;也就是最佳化器不會使用的索引。此功能適用於主鍵(明確或隱含)以外的索引。
索引預設為可見。若要明確控制新索引的可見性,請在 CREATE TABLE
、CREATE INDEX
或 ALTER TABLE
的索引定義中,使用 VISIBLE
或 INVISIBLE
關鍵字。
CREATE TABLE t1 (
i INT,
j INT,
k INT,
INDEX i_idx (i) INVISIBLE
) ENGINE = InnoDB;
CREATE INDEX j_idx ON t1 (j) INVISIBLE;
ALTER TABLE t1 ADD INDEX k_idx (k) INVISIBLE;
若要變更現有索引的可見性,請將 VISIBLE
或 INVISIBLE
關鍵字與 ALTER TABLE ... ALTER INDEX
操作一起使用。
ALTER TABLE t1 ALTER INDEX i_idx INVISIBLE;
ALTER TABLE t1 ALTER INDEX i_idx VISIBLE;
關於索引是否可見或隱形的資訊,可從 Information Schema 的 STATISTICS
資料表或 SHOW INDEX
輸出中取得。例如:
mysql> SELECT INDEX_NAME, IS_VISIBLE
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 't1';
+------------+------------+
| INDEX_NAME | IS_VISIBLE |
+------------+------------+
| i_idx | YES |
| j_idx | NO |
| k_idx | NO |
+------------+------------+
隱形索引可以在不進行破壞性變更(如果索引最終需要,則必須還原)的情況下,測試移除索引對查詢效能的影響。對於大型資料表,捨棄與重新新增索引的成本可能很高,而將其設為隱形和可見是快速、就地執行的操作。
如果最佳化器實際上需要或使用設為隱形的索引,則有幾種方法可以注意到其不存在對資料表查詢的影響。
對於包含參考隱形索引的索引提示的查詢,會發生錯誤。
Performance Schema 資料顯示受影響查詢的工作負載增加。
查詢具有不同的
EXPLAIN
執行計畫。先前未出現在慢速查詢記錄中的查詢會出現在其中。
optimizer_switch
系統變數的 use_invisible_indexes
旗標,控制最佳化器是否使用隱形索引來建構查詢執行計畫。如果旗標為 off
(預設),則最佳化器會忽略隱形索引(與引入此旗標之前的行為相同)。如果旗標為 on
,隱形索引仍為隱形,但最佳化器會在建構執行計畫時將其納入考量。
使用 SET_VAR
最佳化器提示來暫時更新 optimizer_switch
的值,您可以僅針對單一查詢啟用隱形索引,如下所示:
mysql> EXPLAIN SELECT /*+ SET_VAR(optimizer_switch = 'use_invisible_indexes=on') */
> i, j FROM t1 WHERE j >= 50\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: range
possible_keys: j_idx
key: j_idx
key_len: 5
ref: NULL
rows: 2
filtered: 100.00
Extra: Using index condition
mysql> EXPLAIN SELECT i, j FROM t1 WHERE j >= 50\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 5
filtered: 33.33
Extra: Using where
索引可見性不會影響索引維護。例如,索引會繼續根據資料表資料列的變更而更新,而唯一索引會防止將重複項目插入資料行,無論索引是可見還是隱形。
如果資料表在 NOT NULL
資料行上具有任何 UNIQUE
索引,則沒有明確主鍵的資料表仍然可能具有有效的隱含主鍵。在這種情況下,第一個這類索引會對資料表資料列施加與明確主鍵相同的限制,並且該索引無法設為隱形。請考慮下列資料表定義:
CREATE TABLE t2 (
i INT NOT NULL,
j INT NOT NULL,
UNIQUE j_idx (j)
) ENGINE = InnoDB;
定義不包含明確的主鍵,但 NOT NULL
資料行 j
上的索引會對資料列施加與主鍵相同的限制,因此無法設為隱形。
mysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE;
ERROR 3522 (HY000): A primary key index cannot be invisible.
現在假設在資料表中新增了明確的主鍵。
ALTER TABLE t2 ADD PRIMARY KEY (i);
明確的主鍵無法設為隱形。此外,j
上的唯一索引不再充當隱含主鍵,因此可以設為隱形。
mysql> ALTER TABLE t2 ALTER INDEX j_idx INVISIBLE;
Query OK, 0 rows affected (0.03 sec)