概要
MySQLのEXPLAINを読むと良いぞ。
というか読まなきゃダメな時がいつかくる。
各項目の説明についてはこの記事がよくまとまってる。(参考にさせていただきました)
MySQL EXPLAINのそれぞれの項目についての覚書
なんでEXPLAINが大事なの?
EXPLAINは「実行計画」を表示してくれる。どういう順序で、どういう方法でデータを取ってくるか表示してくれるので、クエリのパフォーマンスをチェックすることができる。
スロークエリが発生していたら必ずEXPLAINする癖をつけよう。発生していなくても、自信がなかったらEXPLAINしよう。
RDBMSによって出し方や出力が異なるので注意。
今回はMySQLの話。
そもそも遅くなる要員(よく見かけるやつら)
EXPLAINを見る前に、SQLがなぜ遅くなるのか把握してきたい。
インデックスを使っていない・設定していない
言わずもがな。フルテーブルスキャンって感じ。
O(n)の計算量。インデックスを使えばO(logn)。
相関サブクエリ
二重ループが走ることになる。外側のクエリでヒットしたデータ一件ずつに対してサブクエリが実行される。
O(nm)の計算量のイメージ。
filesort
ソートにクイックソートを使う。O(nlogn)。
インデックスを使ったソートの方が圧倒的に早い(というかインデックスつきのカラムは実質ソートされた状態でデータが保存されている)。
temporary
一時テーブルを使ってソートする。filesortはオンメモリで行うが、データ量が大きくなった場合は一時テーブルを作って、そこからselectする形をとる。
I/Oが重くなるだけでなくテーブルを一回作って書き込むわけだからそりゃ重い。
インデックスが有効活用できない
実質O(n)の計算量。フルインデックススキャンとかその辺。結局O(n)になる
例えば10000件データが入っているテーブルを検索して9999件ヒットする絞り込み条件を選択した場合、インデックスが設定されているカラムで条件を指定していたとしてもほとんど意味がない。
見るべきところ
上で述べたことが、EXPLAINのどこに現れるのか
select_type
DEPENDENT SUBQUERY
に注意。相関サブクエリを意味する。
外側のクエリで十分絞り込めていれば遅くはならない。
type
index
、 ALL
に注意。
フルインデックススキャン、フルテーブルスキャンになり、インデックスが有効活用できていない。
key
null
に注意。
インデックスが使われていないことを意味する。
ここが null
の場合は possible_keys を見ると良い。利用可能なインデックスを探す。
ただしインデックスが設定してあっても利用されないことがあるので注意。
rows
数字が大きいと注意
テーブルから取得する予想件数が多いことになるので、単純に n が大きくなる。I/Oも辛くなる。
特に DEPENDENT SUBQUERY
や filesort
、 temporary
との合わせ技が発揮されると一瞬で死ぬ。
filteredの数字が小さいとまだ救われる(filteredは絞り込まれる割合を百分率で表す)
extra
Using filesort
、 Using temporary
に注意。
まとめ
EXPLAINの結果をしっかり見て、ボトルネックを探そう。