explainで確認するポイント(SQL速度改善)

commits2 min read読了の目安(約1900字

はじめに

Mysql(MariaDB)を使っていてSQLの実行が遅い時など、SQLのチューニングが必要になってきた場合にSQLの実行計画をexplainで確認しましょう。

> select * from menu;

というSQLの実行計画を確認する場合、先頭に「explain」を付けます。

> explain select * from menu;
+------+-------------+-------+------+---------------+------+---------+------+------+-------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------+
|    1 | SIMPLE      | menu  | ALL  | NULL          | NULL | NULL    | NULL |    4 |       |
+------+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.000 sec)

explain 出力フォーマット

explainが出力できたら読み方を確認しましょう。

カラム 意味
id SELECT 識別子
select_type SELECT 型
table 出力行のテーブル
partitions 一致するパーティション
type 結合型
possible_keys 選択可能なインデックス
key 実際に選択されたインデックス
key_len 選択されたキーの長さ
ref インデックスと比較されるカラム
rows 調査される行の見積もり
filtered テーブル条件によってフィルタ処理される行の割合
Extra 追加情報

参照:mysql8.0リファレンス

見ておきたいポイント

explainを実行したら結果の中で特に確認しておきたいポイントとして「type」「key」「Extra」の3カラムに注目して見ていきます。

「type」結合型

typeカラムにテーブルの結合方法が出力されます。
注意したい出力は「ALL」です。「ALL」が出力された場合は、そのテーブルの全行が読みだされています。(フルテーブルスキャンが行われています)

意図的に全行を読み出しているのであれば問題ありませんが、WHERE句などでレコードの抽出を行っているのに「type」が「ALL」となった場合、フルテーブルスキャンが行われるコストの高い検索となっている可能性があるため見直しが推奨されます。

「key」実際に選択されたインデックス

インデックスが効いてない場合は「NULL」になります。
インデックスが使われていなかったらインデックスを追加するか、インデックスが使われるようなSQLに変更する必要があります。インデックスが使われていても意図するインデックスが使われていなかったりもする可能性もあるので確認しておきましょう。

インデックスが追加できない(インデックスの追加が不適な構造)などの場合、SQL側で処理をしないでプログラム側に処理を移す事も検討すると良いと思います。

「Extra」追加情報

SQLを改善するヒントが追加情報に含まれますので参考にしましょう。

最後に

最近は SQL ではなくプログラム に処理が移譲される傾向があり、あまり複雑なSQLにする事は多くないと思いますが、紙に印刷するとA4が3枚くらいになる長文のSQLというのもレガシーなシステムに存在したりするので、切れるカードの1つとしてexplainがある事を頭の片隅に入れておくと良いかもしれません。

「explainを確認するポイント(SQL速度改善)」でした。いかがでしたでしょうか。プログラムとSQLの両方からプログラムを改善していきたいと思います。