MySQL の EXPLAIN で実行計画を読み解く

クエリが遅いとき、まず確認すべきなのが実行計画です。MySQL では EXPLAIN 文を使うことで、クエリがどのように実行されるかを事前に把握できます。

EXPLAIN の基本的な使い方

調べたい SELECT 文の前に EXPLAIN を付けるだけです。

EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

結果は表形式で返され、各列がクエリ実行の重要な情報を示しています。

主要な列の意味

列名意味注目ポイント
typeアクセスタイプALL は要注意
key使用インデックスNULL なら改善余地あり
rows推定走査行数大きいほど遅い

type 列は特に重要で、性能に直結します。良い順に並べると以下のようになります。

system(1行のみのテーブル)
const(主キーで1行特定)
eq_ref(JOINで主キー参照)
ref(インデックス参照)
range(範囲検索)
index(インデックスフルスキャン)
ALL(テーブルフルスキャン)

ALL が表示されたら、インデックスが使われていない可能性が高いです。数万行以上のテーブルで ALL が出ている場合は、必ず対処を検討してください。

Extra 列の読み方

Extra 列には追加情報が表示されます。よく見るものを押さえておきましょう。

Using index

カバリングインデックスが使われており、テーブル本体へのアクセスが不要な状態です。これは良い兆候です。

Using where

WHERE 句でフィルタリングが行われています。インデックスで絞り込めなかった行をストレージエンジンレベルで除外しているということです。

Using temporary

一時テーブルが作成されています。GROUP BY や DISTINCT で発生しやすく、大量データでは遅くなる原因になります。

Using filesort

ソート処理が発生しています。インデックスでソート順を満たせない場合に出現し、パフォーマンス低下の原因になりえます。

EXPLAIN ANALYZE で実測値を確認

MySQL 8.0.18 以降では EXPLAIN ANALYZE が使えます。これは実際にクエリを実行し、推定値ではなく実測値を返してくれます。

EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 100;

出力には実際の実行時間やループ回数が含まれるため、より正確なボトルネック特定が可能です。ただし実際にクエリが実行される点には注意してください。本番環境で重いクエリに対して実行すると負荷がかかります。

実践的な確認フロー

EXPLAIN の結果を見たら、以下の順序でチェックするのがおすすめです。

type が ALL になっていないか確認

key が NULL でないか確認

rows が想定より大きすぎないか確認

Extra に Using temporary や Using filesort がないか確認

これらに問題があれば、インデックスの追加やクエリの書き換えを検討します。EXPLAIN を習慣的に使うことで、本番リリース前に遅いクエリを発見できるようになります。