MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  不可視のインデックス

8.3.12 不可視のインデックス

MySQL では、不可視のインデックス (オプティマイザで使用されないインデックス) がサポートされています。 この機能は、主キー以外のインデックス (明示的または暗黙的) に適用されます。

インデックスはデフォルトで可視化されます。 新しいインデックスの可視性を明示的に制御するには、CREATE TABLECREATE 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;

インデックスが可視か不可視かに関する情報は、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         |
+------------+------------+

不可視のインデックスを使用すると、インデックスが必要になった場合に元に戻す必要がある破壊的な変更を行わずに、クエリーのパフォーマンスに対するインデックスの削除の影響をテストできます。 大規模なテーブルの場合、インデックスを削除して再追加するとコストがかかる可能性がありますが、インデックスを非表示にして可視にすると、高速なインプレース操作になります。

インデックスが実際に不可視になった場合、またはオプティマイザによって使用された場合は、そのインデックスが存在しないことがテーブルのクエリーに与える影響に注意する方法がいくつかあります:

  • 不可視インデックスを参照するインデックスヒントを含むクエリーでは、エラーが発生します。

  • パフォーマンススキーマデータは、影響を受けるクエリーのワークロードの増加を示します。

  • クエリーには、異なる 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)

関連キーワード:  インデックス, テーブル, 不可視, InnoDB, クエリー, TABLE, idx, オプティマイザ, ステートメント, 結合