MySQLでクエリをExplainした時にpossible_keysに、IDX_IMPORT, IDX_FSEARCH, IDX_STAT等と複数の候補が存在してkeyにIDX_STATが選択されている時、実際にはIDX_IMPORTの方が高速だったり、他のインデックスよりIDX_STATが低速だったりする時、このインデックスを利用すると高速・低速であるというのをオプティマイザへ知らせる方法としてインデックスヒントがある。
インデックスヒントは
SELECT * FROM estimates USE INDEX(IDX_IMPORT, IDX_FSEARCH) WHERE total>=10000 AND type=1
のように、テーブルに対してUSE/IGNORE/FORCEにより指定する。
USE INDEXはその名の通り指定したインデックスを使用することを推奨するので、インデックス候補中で速い物を指定する。
FORCE INDEXはフルスキャンが非常に重いことを知らせた上で、指定したインデックスを使用することを推奨する。
※特定の条件ではインデックススキャンよりもフルスキャンの方が高速となるパターンがあるので、USEでインデックスを知らせてもそれを使用しないことがあるが、FORCE指定するとフルスキャンを回避してインデックスを使う様になる。 FORCE指定した場合、フルスキャンよりも低速になる可能性もあるので、実データで検証した上で指定した方が良い。
IGNORE INDEXは、逆に使用しないインデックスを指定するので、インデックス候補中で明らかに低速なインデックスがある場合にそれを除外するために使う。
USEとFORCEを比較
EXPLAIN SELECT id FROM estimates USE INDEX (PRIMARY) WHERE type=1 ORDER BY id
possible_keys:NULL key:NULL
EXPLAIN SELECT id FROM estimates FORCE INDEX (PRIMARY) WHERE type=1 ORDER BY id
possible_keys:NULL key:PRIMARY
ちなみに、ヒントを与えない場合は、possible_keys:NULL key:NULLである。 このクエリを実際に発行すると、USEで0.25秒、FORCEで0.33秒と言うことで、インデックスを使っているけど逆に遅くなった。
インデックスは何でも張って何でも使えばいいと言う物ではないと言うことだ。
なお、このようにインデックスを使用すると遅くなる状況でオプティマイザがインデックスを使用するのを防ぐために、USE INDEX ()として、インデックスを使用しないことを明示することも出来る。
(22166)