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;
若要變更現有索引的可見性,請在 ALTER TABLE ... ALTER INDEX
操作中使用 VISIBLE
或 INVISIBLE
關鍵字。
ALTER TABLE t1 ALTER INDEX i_idx INVISIBLE;
ALTER TABLE t1 ALTER INDEX i_idx VISIBLE;
關於索引是可見還是隱形的資訊,可從資訊綱要 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)