367
344

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【MySQL】遅いselect文の原因を調査する【explainの読み方】

Last updated at Posted at 2017-08-12

ExplainでSQLのボトルネックを調査する

→select文の前に「explain」をつけて実行してみる

explain select * from tableName;

実行結果の読み方

select_type

サブクエリの場合

説明
PRIMARY 外部のクエリ
SUBQUERY 相関関係のないサブクエリ
DEPENDENT SUBQUERY 相関関係のあるサブクエリ
UNCACHEABLE SUBQUERY 実行のたびに結果が変わるかもしれないサブクエリ
DERIVERD from句で使われるサブクエリ
外部クエリ→サブクエリの順序で実行されるが、DERIVERDのときだけはサブクエリ→外部クエリと実行順所が逆になる。

UNIONの場合

説明
PRIMARY unionのときに最初にフェッチされるテーブル
UNION 2番目以降にフェッチされるテーブル
UNION RESULT UNIONの実行結果
DEPENDENT UNION DEPENDENT SUBQUERYがUNIONになっている場合
UNCACHEABLE UNION UNCACHEABLE SUBQUERYがUNIONになっている場合
UNOINは先頭から順に処理されていくので、処理順序がわかりやすい・・・はず。

type

対象のテーブルに対してのアクセス方法。
致命的なものは見れば一発でわかる・・・らしい。

説明
ALL フルスキャンなので一番重い。改善必須:warning:
index フルインデックススキャン。インデックスをALL検索するのでこれまた重い。改善必須:warning:
ref インデックスを使った検索
range インデックスを使った範囲検索。
eq_ref joinのときにPKやユニークキーを使う場合。joinのときはこの値になれば最速。
const join以外でPKやユニークキーを使う場合。最速。

key

テーブルにアクセスするために使ったindexを示す。
ちなみに、possible_keysは「使える候補」で、実際につかったかどうかはkeyの値を見る。

key_len

選択されたキーの長さ。
インデックスのキー長が短いほうが高速になるので、迷ったら長さの短いほうにインデックスをつけるといい。

rows

selectの取得件数の見積もり。
ざっくりとしたものなので、where句次第ではもっと少ない件数が返ってくることもある。

extra

ほかに使用している条件などがあれば、ここに出力される。

チューニング方法の例

type=null かつ key=null の場合

→インデックスが張られてない&テーブルのフルスキャンが行われている。
where条件で使うカラムにインデックスを張る。
もしくは、インデックスが張られたカラムをwhere条件の中に追加する。

extra=Using filesort もしくは extra=temporary

→order byに指定しているカラムにインデックスを張る。
Javaだと、Listで取得してCollection.sort()もできるので、Java側にソート処理を入れるものアリかもしれない。
「extra=temporary」はjoinしているときに出現するので、joinしているテーブルのどこかにインデックスを張ればよい。

インデックスを張ってあるはずなのにtype=all

→複合インデックスが使われてない。
複合インデックスが張ってあるカラムを、すべてwhere条件に使用する。
インデックスと同じ順序でwhere条件を組み立てること!

possible_keysに出力があるのにkey=nullで使われてない

→MySQLの仕様が原因かもしれないので、SQLそのものを作り変える。
例)インデックスが張ってあるカラムをwhere条件に使用しているのに、テーブル検索が実施されている
MySQLが「インデックス検索よりもテーブル検索が早い」と判断してしまうことがあるようです。
SQLのつくりを変えるなどの、大きな変更が必要になる。
(仕様や設計を見直すことも視野に入れた方がよい)

その他やってみるといいかもしれない方法

joinのときにインデックスを使うような記述を追加する

SELECT * FROM tableA aa LEFT JOIN tableB bb USE INDEX(index名)
SELECT * FROM tableA aa LEFT JOIN tableB bb FORCE INDEX(index名) /* USEが効かない場合はこちら */
367
344
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
367
344

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?