MySQLのEXPLAIN(実行計画)の見方

MySQLのEXPLAIN(実行計画)の見方

MySQLのEXPLAINコマンドは、クエリがどのように実行されるかを可視化するために使用されるツールです。
クエリのパフォーマンスを最適化する際に有用で、テーブルのスキャン方法やインデックスの使用状況などを確認できます。
実行計画の見方を理解することで、非効率なクエリを特定し、適切なインデックスの作成やクエリの書き換えなどでパフォーマンスを改善する手助けになります。

EXPLAINの出力にはいくつかのカラムがあり、それぞれが異なる情報を提供します。
以下は主要なカラムとその意味です。

1. id

idカラムは、クエリ内のSELECT文の識別子を示します。
idが同じ行は、同じクエリブロックに属していることを示し、通常は同時に処理されます。
idが異なる場合は、それぞれの部分が別の順番で評価されます。
idが大きいほど、評価される順序が遅くなります。

2. select_type

select_typeは、クエリの種類やサブクエリの位置を示します。
主なタイプには以下があります。

  • SIMPLE: サブクエリやUNIONが含まれないシンプルなSELECT文
  • PRIMARY: クエリの最上位のSELECT文
  • SUBQUERY: サブクエリ
  • DERIVED: 派生テーブルを使っている場合
  • UNION: UNIONを使っている場合の一部

3. table

tableはクエリで参照しているテーブルの名前、または派生テーブルや一時テーブルを示します。

4. type

typeカラムは、テーブルアクセスの方法、つまり、どの程度効率的にデータにアクセスできるかを示します。
主要な値は以下の通りです。

  • ALL: フルテーブルスキャン(最も非効率)
  • index: インデックス全体のスキャン
  • range: インデックスの範囲スキャン
  • ref: インデックスの参照(複数の行を参照)
  • eq_ref: 一致する行が1つだけの場合(最も効率的)
  • const: 定数テーブルとして扱われる場合(効率的)

typeがALLの場合は、テーブル全体をスキャンしているので、インデックスを利用するか、クエリの最適化が必要な可能性があります。
※フルスキャンだから遅いという結論に必ずしもなるわけではないので、注意が必要です。

5. possible_keys

possible_keysカラムは、クエリの実行に使用できる可能性のあるインデックスのリストを表示します。
このフィールドにはインデックスが指定されていない場合はNULLになります。

6. key

keyは、実際に使用されているインデックスを示します。
もしkeyがNULLであれば、インデックスが使用されていないことを意味します。
possible_keysにインデックスが表示されていても、keyがNULLであれば、最適なインデックスが使用されていない可能性があるので、クエリやインデックスの見直しが必要です。

7. key_len

key_lenは、使用されているインデックスの長さ(バイト単位)を示します。
この値が短すぎる場合、インデックスが一部しか使われていないことを意味します。

8. ref

refカラムは、インデックスに基づいて検索されるカラムや定数を示します。
たとえば、constやNULL、または別のテーブルのカラムが表示されることがあります。

9. rows

rowsカラムは、クエリ実行中にMySQLが読み込むと予想している行数を示します。
この値が大きいほど、クエリが多くのデータを処理している可能性があり、パフォーマンスに影響を与えることがあります。

10. Extra

Extraカラムは、クエリの実行に関する追加情報を提供します。
ここには、最適化に関する重要なヒントが表示されることがあります。
よく見られる値は以下の通りです。

  • Using where: WHERE句で条件が適用されていることを示します。
  • Using index: クエリがインデックスだけを使ってデータを取得していることを示します。

これは効率的です。

  • Using temporary: 一時テーブルが使用されていることを示します。

一般的に避けるべきです。

  • Using filesort: ファイルソートが使用されていることを示し、パフォーマンスの低下を引き起こす可能性があります。

実例

次のクエリの例を見てみます。

EXPLAIN SELECT * FROM employees WHERE age > 30;

これに対してのEXPLAINの結果は以下のようになるかもしれません。

id select_type table type possible_keys key key_len ref rows Extra
---- ------------- ----------- ------ --------------- ------ --------- ------ ------ ----------------
1 SIMPLE employees ALL NULL NULL NULL NULL 1000 Using where

この場合、typeがALLであるため、employeesテーブル全体がスキャンされ、インデックスが使用されていないことが分かります。
インデックスが存在しない、またはインデックスを使用していないため、効率が悪い可能性があります。
このような場合、ageカラムに対してインデックスを追加することで、パフォーマンスを改善できる可能性があります。

まとめ

EXPLAINコマンドを使うことで、クエリの実行計画を確認し、どのようにデータにアクセスしているかを把握できます。
各カラムの意味を理解し、クエリやインデックスを適切に最適化することで、MySQLのパフォーマンスを大幅に向上させることができます。