VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
EXPLAIN です。MySQL がそのクエリをどう実行する計画なのかを正確に示します。どのインデックスを使うか、何行をスキャンする見込みか、どこで高コストな処理をしているかです。読めるようになれば、ほぼどんな遅いクエリでも修正できます。
EXPLAIN の実行
任意のSELECT の前に EXPLAIN を付けます。
重要な列
完全なEXPLAIN の行は次のようになります。
type — MySQL がテーブルをスキャンする方法
これが最も重要な列です。アクセス方法を示し、速い順に次のとおりです。
ALL が修正すべきものです。 MySQL がテーブルのすべての行を読んでいることを意味します。100 万行のテーブルでは、クエリを実行するたびに 100 万回の読み取りです。
key — MySQL が選んだインデックス
NULL はインデックスが使われなかったことを意味します。possible_keys にインデックスが列挙されているのに key が NULL の場合、MySQL はフルスキャンの方が安いと判断しました。通常はテーブルが小さいか、クエリの選択性が十分でないためです。
rows — 検査される行数の見積もり
見積もりであり、保証ではありません。MySQL は統計を使ってこの数値を算出します。rows: 1 のクエリは速く、本番テーブルでの rows: 5000000 は問題です。
Extra — 追加の実行詳細
Extra 列には重要なフラグが入ります。
大きなテーブルで
Using filesort と Using temporary が同時に出るのは危険信号です。
実例
ALL)と filesort です。複合インデックスで両方を修正します(インデックス設計の原則は MySQL のインデックスの仕組みを参照してください)。
rows は 1,000,000 から 4,200 に減りました。type は ref になり、status での等価ルックアップです。インデックスがすでに各 status 値の中で行を created_at 順に並べているため、filesort は消えました。
EXPLAIN ANALYZE
EXPLAIN ANALYZE は実際にクエリを実行し、見積もりと並べて実際の時間を返します。
cost と rows はオプティマイザの見積もりです。actual time と actual rows は実際に起きたことです。見積もりと実際の行数の差が大きい場合は統計が古いことを意味するため、ANALYZE TABLE orders を実行して更新します。
よくある質問
EXPLAIN とカバリングインデックスの関係は何ですか?
Extra: Using index は、MySQL がカバリングインデックスを使っていることを意味します。テーブルの行を読まずに、インデックスだけでクエリに完全に応答できます。これは読み取りの多いテーブルで利用できる最も効果の大きい最適化の 1 つです。設計方法は MySQL のカバリングインデックスを参照してください。
クエリに type: index が出ます — 問題ありませんか?
あまりよくありません。type: index は、MySQL が(テーブルではなく)インデックス全体をスキャンしたことを意味します。ALL より速いですが、それでもフルスキャンです。クエリがすべての行を必要とするものの、インデックスから満たせる場合に現れます。大きなテーブルでこれに当たる場合は、カバリングインデックスや WHERE 句でスキャンを絞り込めないか確認してください。
作成したインデックスを MySQL が無視するのはなぜですか?
オプティマイザは統計に基づいてインデックスを選びます。テーブルが小さい場合、MySQL はフルスキャンの方が安いと判断することがあります。統計が古い場合、インデックスの選択性を過小評価することがあります。ANALYZE TABLE を実行して統計を更新し、EXPLAIN を再確認してください。
INSERT、UPDATE、および DELETE に EXPLAIN を使えますか?
はい。MySQL 8.0 以降では、EXPLAIN はすべての DML ステートメントで機能します。出力は変更対象の行へのアクセス方法を示すため、UPDATE や DELETE が遅いときに役立ちます。
どのクエリから EXPLAIN すべきかを特定する必要がある場合は、MySQL のスロークエリログがサーバー上で最も遅いクエリを記録し、合計時間で順位付けします。
トラブルシューティング
関連項目
- MySQL のインデックスの仕組み — EXPLAIN が報告している B ツリー構造
- MySQL のカバリングインデックス — Extra の
Using indexの意味と、それに到達する方法 - MySQL のスロークエリログ — EXPLAIN を実行する価値のあるクエリを見つける
- MySQL のクエリが遅いのはなぜ? — EXPLAIN がつながるチューニングのワークフロー
- MySQL のページネーション: キーセット vs OFFSET — キーセットページネーションがスキャンではなくシークすることの確認
- MySQL の LIMIT — チュートリアルでのプラン行の解説