Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

EXPLAIN

クエリがどのように実行されるかを確認する命令です。インデックスの使用状況やパフォーマンス問題の調査に使います。

構文
-- クエリの実行計画を確認します(MySQL・PostgreSQL)。
EXPLAIN SELECT ...;

-- 実際に実行して統計付きの実行計画を確認します(PostgreSQL)。
EXPLAIN ANALYZE SELECT ...;

-- MySQL で実際に実行して詳細な統計を確認します。
EXPLAIN ANALYZE SELECT ...;

-- JSON形式で実行計画を確認します(MySQL)。
EXPLAIN FORMAT = JSON SELECT ...;
出力列の読み方(MySQL)
列名概要
idクエリ内のSELECT識別子です。サブクエリがある場合に複数の行が表示されます。
select_typeSELECT の種類を示します。SIMPLE(サブクエリなし)・SUBQUERY・DERIVED(FROM句サブクエリ)などがあります。
tableこのステップで参照しているテーブル名です。
typeテーブルへのアクセス方法です。const・ref・range・index・ALLの順に効率が下がります。
possible_keys利用できる可能性があるインデックスの一覧です。
key実際に使用されたインデックスです。NULL の場合はフルスキャンが行われています。
rowsスキャンが必要と推定される行数です。小さいほど効率的です。
Extra追加情報です。Using index(カバリングインデックス)・Using filesort(ソート処理)などが表示されます。
サンプルコード
-- 基本的な実行計画を確認します。
EXPLAIN
SELECT name, email
FROM members
WHERE email = 'tanaka@example.com';

-- JOIN を含むクエリの実行計画を確認します。
EXPLAIN
SELECT m.name, o.total
FROM members m
JOIN orders o ON m.member_id = o.member_id
WHERE m.status = 'active';

-- JSON形式で詳細な実行計画を確認します(MySQL)。
EXPLAIN FORMAT = JSON
SELECT * FROM orders WHERE ordered_at >= '2025-01-01';

-- 実行計画と実際の実行統計を同時に確認します(MySQL 8.0.18以降)。
EXPLAIN ANALYZE
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
実行結果
-- EXPLAIN SELECT name, email FROM members WHERE email = 'tanaka@example.com'; の結果例
-- インデックスが設定されている場合:
-- +----+-------------+---------+------+-------------------------+-------------------------+---------+-------+------+-------+
-- | id | select_type | table   | type | possible_keys           | key                     | key_len | ref   | rows | Extra |
-- +----+-------------+---------+------+-------------------------+-------------------------+---------+-------+------+-------+
-- |  1 | SIMPLE      | members | const| idx_members_email_unique| idx_members_email_unique| 1022    | const |    1 |       |
-- +----+-------------+---------+------+-------------------------+-------------------------+---------+-------+------+-------+

-- インデックスが設定されていない場合(type が ALL = フルスキャン):
-- +----+-------------+---------+------+---------------+------+---------+------+------+-------------+
-- | id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
-- +----+-------------+---------+------+---------------+------+---------+------+------+-------------+
-- |  1 | SIMPLE      | members | ALL  | NULL          | NULL | NULL    | NULL | 5000 | Using where |
-- +----+-------------+---------+------+---------------+------+---------+------+------+-------------+
データベース別の書き方

PostgreSQL は『EXPLAIN』に加え、実際に実行して統計を取得する『EXPLAIN ANALYZE』が使用できます。

-- 実行計画の確認(PostgreSQL)。
EXPLAIN SELECT name, email FROM members WHERE email = 'tanaka@example.com';

-- 実際に実行して統計を取得します(PostgreSQL)。
EXPLAIN ANALYZE SELECT name, email FROM members WHERE email = 'tanaka@example.com';

Oracle は『EXPLAIN PLAN FOR』で実行計画をPLAN_TABLEに保存し、『DBMS_XPLAN.DISPLAY』で表示します。

-- 実行計画を保存します(Oracle)。
EXPLAIN PLAN FOR
SELECT name, email FROM members WHERE email = 'tanaka@example.com';

-- 保存した実行計画を表示します(Oracle)。
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

SQL Server は『SET SHOWPLAN_ALL ON』または『実際の実行プランを含める』で確認します。推定プランのみ確認する場合は実行前に設定します。

-- 推定実行計画を表示します(SQL Server)。
SET SHOWPLAN_ALL ON;
GO
SELECT name, email FROM members WHERE email = 'tanaka@example.com';
GO
SET SHOWPLAN_ALL OFF;

SQLite は『EXPLAIN QUERY PLAN』で簡易的な実行計画を確認できます。

-- 実行計画の確認(SQLite)。
EXPLAIN QUERY PLAN
SELECT name, email FROM members WHERE email = 'tanaka@example.com';
概要

『EXPLAIN』の出力で最も重要な列は『type』と『key』です。『type』が『ALL』の場合はフルテーブルスキャン(全行走査)が発生しており、テーブルが大きいとパフォーマンスに直結します。『key』に目的のインデックス名が表示されていればインデックスが使用されています。

『rows』は推定スキャン行数です。JOINを含むクエリでは各テーブルのrowsを掛け合わせた値が総スキャン量の目安になります。この値が大きい場合はインデックスの追加や、クエリの書き直しを検討しましょう。

インデックスの作成・削除は『CREATE INDEX』を参照してください。クエリのパフォーマンスを根本から改善するには、適切なインデックス設計が重要です。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。