- MySQL
- 2022-10-27 - 更新:2022-11-08
MySQLのクエリ実行速度が遅いので調査・改善する機会がありましたので、それについて書いておきたいと思います。
チェックポイントは以下の通りです。
- 適切なインデックスが貼られているか確認
- EXPLAINで実際に使用されたインデックスの確認
適切なインデックスが貼られているか確認
まずは適切なインデックスが貼られているかを確認します。
ここをチェックしないと始まらないのでしっかりと確認します。
適切なインデックスが貼られていない場合は追加します。
EXPLAINで実際に使用されたインデックスの確認
インデックスを追加して、それでも実行速度に改善が見られない場合は、そのインデックスが実際に使われているかを調べます。
SQL文の前にEXPLAIN
を付加して実行します。
EXPLAIN
は、クエリー実行計画(MySQLがクエリーをどのように実行するかの説明)を取得するために使用されます。
EXPLAIN SELECT ...
表示された結果の内容を抜粋してご説明します。
possible_keys
利用可能なインデックスの一覧(候補)
key
利用可能なインデックスのうち、実際に選択されたインデックス
type
const
はPKやUNIQUEの等価検索時のタイプなので問題なし
eq_ref
はJOINにおいてPRIMARY KEYまたはUNIQUE KEYが利用される時のアクセスタイプ。constと似ているがJOINで用いられるところが違う。
ref
だとユニーク(PRIMARY or UNIQUE)でないインデックスを使って等価検索(WHERE key = value)を行った時に使われるアクセスタイプ。大抵は問題なし。
range
はちょっと注意。
index
はかなり注意。(場合によってはダメ)
ALL
は全表操作。全くダメ。
Extra
付帯情報
Using where
気にする必要なし
Using index
クエリがインデックスだけを用いて解決できることを示す
Using index condition
クエリがインデックスの値を一部利用できることを示す
Using filesort
filesort(クイックソート)でソートを行っていることを示す。これが出ている場合、インデックスをうまく使ってソートをしなくて済む設計にできないか考える
使用するインデックスを明示的に指定する
基本的にはオプティマイザと呼ばれる機能があり、それが自動的に使用するインデックスを判別します。
但し、適切なインデックスが貼ってあっても、オプティマイザが別のインデックスを選んでしまうということがあります。
その場合、SQL文の中で明示的に使用するインデックスを指定することができます。
使用するインデックスを指定するにはUSE INDEX
構文を使います。
SELECT * FROM table_name USE INDEX (インデックス名) WHERE ...
逆に指定したインデックスを除外することもできます。
SELECT * FROM table_name IGNORE INDEX (インデックス名) WHERE ...
最後に
私の場合、適切なインデックスを貼り直したが、オプティマイザがそれを選んでくれなくて、明示的に指定することでクエリ実行速度を改善しました。
以下は公式リファレンスなので参考にしてください。
EXPLAIN構文
https://dev.mysql.com/doc/refman/5.6/ja/explain.html
インデックスヒントの構文
https://dev.mysql.com/doc/refman/5.6/ja/index-hints.html