文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美國信紙尺寸) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  隱形索引

10.3.12 隱形索引

MySQL 支援隱形索引;也就是說,最佳化器不會使用的索引。此功能適用於主索引鍵(明確或隱含)以外的索引。

預設情況下,索引是可見的。若要明確控制新索引的可見性,請在 CREATE TABLECREATE INDEXALTER TABLE 的索引定義中,使用 VISIBLEINVISIBLE 關鍵字。

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 操作中使用 VISIBLEINVISIBLE 關鍵字。

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)