インデックスヒントは、クエリー処理中にインデックスを選択する方法に関するオプティマイザ情報を提供します。 ここで説明するインデックスヒントは、セクション8.9.3「オプティマイザヒント」 で説明されているオプティマイザヒントとは異なります。 インデックスヒントとオプティマイザヒントは、別々に、または一緒に使用できます。
インデックスヒントは、SELECT
および UPDATE
ステートメントにのみ適用されます。
インデックスヒントは、テーブル名の後に指定します。 (SELECT
ステートメントでテーブルを指定するための一般的な構文は、セクション13.2.10.2「JOIN 句」 を参照してください。) インデックスヒントを含む個々のテーブルを参照する構文は、次のようになります:
tbl_name [[AS] alias] [index_hint_list]
index_hint_list:
index_hint [index_hint] ...
index_hint:
USE {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
| {IGNORE|FORCE} {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
index_list:
index_name [, index_name] ...
USE INDEX (
ヒントは、名前付きインデックスのいずれかのみを使用してテーブル内の行を検索するように MySQL に指示します。 代替構文 index_list
)IGNORE INDEX (
は、特定のインデックスを使用しないように MySQL に指示します。 これらのヒントは、index_list
)EXPLAIN
によって、MySQL が可能性のあるインデックスのリストから間違ったインデックスを使用していることが示された場合に役立ちます。
FORCE INDEX
ヒントは USE INDEX (
のように機能しますが、テーブルスキャンは very コストが高いとみなされます。 つまり、テーブルスキャンは、名前付きインデックスのいずれかを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。
index_list
)
MySQL 8.0.20 の時点で、サーバーは、インデックスオプティマイザヒント JOIN_INDEX
, GROUP_INDEX
, ORDER_INDEX
、および INDEX
(NO_JOIN_INDEX
, NO_GROUP_INDEX
, NO_ORDER_INDEX
および FORCE INDEX
オプティマイザヒントに相当およびを置き替える)、および NO_INDEX
オプティマイザヒント (IGNORE INDEX
インデックスヒントに相当し、それらを置き換える) をサポートします。 したがって、USE INDEX
、FORCE INDEX
および IGNORE INDEX
は、MySQL の将来のリリースで非推奨になり、後で完全に削除される予定です。 詳細は、インデックスレベルのオプティマイザヒントを参照してください。
各ヒントには、カラム名ではなくインデックス名が必要です。 主キーを参照するには、PRIMARY
という名前を使用します。 テーブルのインデックス名を表示するには、SHOW INDEX
ステートメントまたは INFORMATION_SCHEMA.STATISTICS
テーブルを使用します。
index_name
値は、完全なインデックス名である必要はありません。 インデックス名のあいまいでないプリフィクスにすることができます。 プリフィクスがあいまいな場合は、エラーが発生します。
例:
SELECT * FROM table1 USE INDEX (col1_index,col2_index)
WHERE col1=1 AND col2=2 AND col3=3;
SELECT * FROM table1 IGNORE INDEX (col3_index)
WHERE col1=1 AND col2=2 AND col3=3;
インデックスヒントの構文には、次の特性があります。
構文的には、
index_list
forUSE INDEX
(「「インデックスを使用しない」」を意味する) を省略することが有効です。index_list
forFORCE INDEX
またはIGNORE INDEX
の省略は構文エラーです。ヒントに
FOR
句を追加することで、インデックスヒントの有効範囲を指定できます。 これにより、クエリー処理の様々なフェーズの実行計画のオプティマイザ選択をよりきめ細かく制御できます。 MySQL がテーブル内の行の検索方法および結合の処理方法を決定するときに使用されるインデックスにのみ影響を与えるには、FOR JOIN
を使用します。 行をソートまたはグループ化するためのインデックス使用に影響を与えるには、FOR ORDER BY
またはFOR GROUP BY
を使用します。-
複数のインデックスヒントを指定できます。
SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX FOR ORDER BY (i2) ORDER BY a;
(同じヒント内であっても) 複数のヒントで同じインデックスに名前を付けるとエラーになりません:
SELECT * FROM t1 USE INDEX (i1) USE INDEX (i1,i1);
ただし、同じテーブルに対して
USE INDEX
とFORCE INDEX
を混在させると、エラーが発生します。SELECT * FROM t1 USE INDEX FOR JOIN (i1) FORCE INDEX FOR JOIN (i2);
インデックスヒントに FOR
句が含まれていない場合、ヒントの有効範囲はステートメントのすべての部分に適用されます。 たとえば、次のヒント
IGNORE INDEX (i1)
は次のヒントの組み合わせと同等です。
IGNORE INDEX FOR JOIN (i1)
IGNORE INDEX FOR ORDER BY (i1)
IGNORE INDEX FOR GROUP BY (i1)
MySQL 5.0 では、FOR
句のないヒントスコープは、行の取得にのみ適用されました。 FOR
句が存在しないときにサーバーがこの古い動作を使用するようにするには、サーバーの起動時に old
システム変数を有効にします。 レプリケーションセットアップでこの変数を有効にする場合は注意してください。 ステートメントベースのバイナリロギングでは、ソースとレプリカのモードが異なると、レプリケーションエラーが発生する可能性があります。
インデックスヒントが処理されるとき、これらのインデックスヒントは、型 (USE
、FORCE
、IGNORE
) およびスコープ (FOR JOIN
、FOR ORDER BY
、FOR GROUP BY
) ごとに 1 つのリストに収集されます。 例:
SELECT * FROM t1
USE INDEX () IGNORE INDEX (i2) USE INDEX (i1) USE INDEX (i2);
次と同等です。
SELECT * FROM t1
USE INDEX (i1,i2) IGNORE INDEX (i2);
そのあと、インデックスヒントは、スコープごとに次の順序で適用されます。
{USE|FORCE} INDEX
が存在する場合は、これが適用されます。 (存在しない場合は、オプティマイザによって決定されたインデックスのセットが使用されます。)-
前の手順の結果に対して、
IGNORE INDEX
が適用されます。 たとえば、次の 2 つのクエリーは同等です。SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) USE INDEX (i2); SELECT * FROM t1 USE INDEX (i1);
FULLTEXT
の検索の場合、インデックスヒントは次のように機能します。
自然言語モードの検索の場合、インデックスヒントは暗黙のうちに無視されます。 たとえば、
IGNORE INDEX(i1)
は警告なしで無視され、インデックスは引き続き使用されます。-
ブールモードの検索の場合、
FOR ORDER BY
またはFOR GROUP BY
を含むインデックスヒントは暗黙のうちに無視されます。FOR JOIN
を含むインデックスヒント、またはFOR
修飾子を含まないインデックスヒントは受け付けられます。 ヒントがFULLTEXT
以外の検索に適用される場合とは異なり、このヒントは、クエリー実行のすべてのフェーズ (行の検索と取得、グループ化、および順序付け) に使用されます。 これは、ヒントがFULLTEXT
以外のインデックスに対して指定されている場合でも当てはまります。たとえば、次の 2 つのクエリーは同等です。
SELECT * FROM t USE INDEX (index1) IGNORE INDEX (index1) FOR ORDER BY IGNORE INDEX (index1) FOR GROUP BY WHERE ... IN BOOLEAN MODE ... ; SELECT * FROM t USE INDEX (index1) WHERE ... IN BOOLEAN MODE ... ;