クエリー処理中にインデックスを選択する方法に関する情報をオプティマイザに提供するためのヒントを指定できます。項8.2.8.1. 「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
に指示できます。これらのヒントは、MySQL
が可能なインデックスのリストの中から、間違ったインデックスを利用していることを、index_list
)EXPLAIN
が表示したときに便利なものです。
また、USE INDEX
(
と同様の機能を持つが、テーブルスキャンが非常に負荷が大きいと見なされる点が追加された
index_list
)FORCE INDEX
を使用することもできます。言い換えると、テーブル内の行を見つけるために与えられたインデックスを利用できない場合、テーブルスキャンを利用することができるということです。
各ヒントには、カラムの名前ではなく、インデックスの名前が必要です。PRIMARY
KEY
の名前は
PRIMARY
です。テーブルのインデックス名を表示するには、SHOW
INDEX
を使用します。
index_name
値は、完全なインデックス名である必要はありません。インデックス名のあいまいでない接頭辞にすることができます。接頭辞があいまいな場合は、エラーが発生します。
MySQL 5.1.17
より前のバージョンでは、USE
INDEX
、IGNORE
INDEX
、および FORCE
INDEX
は、MySQL
がテーブル内の行の検索方法および結合の処理方法を決定するときにどのインデックスが使用されるかにのみ影響を与えます。ORDER
BY
または GROUP
BY
節を解決するときにインデックスが使用されるかどうかには影響を与えません。
例:
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;
MySQL 5.1.17 では、インデックスヒントの構文は次の方法で拡張されています。
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);
MySQL 5.1.17
では、インデックスヒントのデフォルトスコープも変更されています。以前は、インデックスヒントは、ORDER
BY
または GROUP
BY
節の解決中ではなく、インデックスがレコードの取り出しにどのように使用されるかにのみ適用されました。5.1.17
では、インデックスヒントに対して
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
検索の場合、MySQL 5.1.31
より前のバージョンではインデックスヒントは機能しません。5.1.31
では、インデックスヒントは次のように機能します。
自然言語モードの検索の場合、インデックスヒントは暗黙のうちに無視されます。たとえば、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 ... ;
インデックスヒントは受け入れられますが、UPDATE
ステートメントに対して無視されます。