クエリー処理中にインデックスを選択する方法に関する情報をオプティマイザに提供するためのヒントを指定できます。セクション13.2.9.2「JOIN 構文」では、SELECT
ステートメントでテーブルを指定するための一般的な構文について説明しています。個々のテーブルの構文 (インデックスヒントの構文を含む) は次のようになります。
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 {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
| FORCE {INDEX|KEY}
[FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
index_list:
index_name [, index_name] ...
USE INDEX (
を指定することによって、テーブル内の行を検索するために、指定されたインデックスの 1 つのみを使用するよう MySQL に指示できます。代わりの構文 index_list
)IGNORE INDEX (
を使用すると、いくつかの特定の (1 つまたは複数の) インデックスを使用しないよう MySQL に指示できます。これらのヒントは、index_list
)EXPLAIN
によって、MySQL が可能性のあるインデックスのリストから間違ったインデックスを使用していることが示された場合に役立ちます。
また、USE INDEX (
と同様の機能を持つが、テーブルスキャンが非常に負荷が大きいと見なされる点が追加された index_list
)FORCE INDEX
を使用することもできます。つまり、テーブルスキャンは、指定されたインデックスのいずれかを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。
各ヒントには、カラムの名前ではなく、インデックスの名前が必要です。PRIMARY KEY
の名前は PRIMARY
です。テーブルのインデックス名を表示するには、SHOW INDEX
を使用します。
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;
インデックスヒントの構文には、次の特性があります。
USE INDEX
に空のindex_list
を指定する (つまり、「インデックスを使用しない」) ことは構文として有効です。FORCE INDEX
またはIGNORE INDEX
に空のindex_list
を指定することは構文エラーです。ヒントに
FOR
句を追加することによって、インデックスヒントのスコープを指定できます。これにより、クエリー処理のさまざまなフェーズに対するオプティマイザの実行計画の選択をよりきめ細かく制御できるようになります。MySQL がテーブル内の行の検索方法および結合の処理方法を決定するときに使用されるインデックスにのみ影響を与えるには、FOR JOIN
を使用します。行をソートまたはグループ化するためのインデックス使用に影響を与えるには、FOR ORDER BY
またはFOR GROUP BY
を使用します。(ただし、テーブルを範囲に含むインデックスが存在し、それがテーブルへのアクセスに使用されている場合、オプティマイザは、そのインデックスを無効にするIGNORE INDEX FOR {ORDER BY|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)
サーバーで、FOR
句が存在しないときに (ヒントが行の取得にのみ適用されるように) ヒントスコープに対する古い動作が使用されるようにするには、サーバーの起動時に古い
システム変数を有効にします。レプリケーションセットアップでこの変数を有効にする場合は注意してください。ステートメントベースのバイナリロギングで、マスターとスレーブに異なるモードを指定するとレプリケーションエラーが発生する場合があります。
インデックスヒントが処理されるとき、これらのインデックスヒントは、型 (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(i)
は警告なしで無視され、インデックスが引き続き使用されます。ブールモードの検索の場合、
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 ... ;