EXPLAINコマンドは、PostgreSQLがクエリを「どうやって実行するつもりか」をクリスタルボールで覗く感じだけど、EXPLAIN ANALYZEは本物の探偵になって、実際に何が起きたのかを突き止める感じだよ。
EXPLAINとEXPLAIN ANALYZEの主な違い:
EXPLAIN – これは理論で、PostgreSQLがクエリをどうやって実行するかの計画を見せてくれる。たとえば、行数(rows)やコスト(cost)みたいな予想値が見える。
EXPLAIN ANALYZE – これは実践。PostgreSQLが実際にクエリを実行して、次のことを見せてくれる:
- 各ステップで実際に処理された行数。
- 各オペレーションの実際の実行時間。
- 計画の予想(
rowsやcost)との比較。
例:クエリが100行を処理するはずなのに、実際は10,000行処理してたら、EXPLAIN ANALYZEがそのヤバい事実をすぐに暴いてくれる!
基本的な構文と使い方
EXPLAINと同じく、EXPLAIN ANALYZEも超簡単に使える。EXPLAINコマンドにANALYZEを付け足すだけ。
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20;
PostgreSQLがやること:
- クエリを実行する。
- 実行プランの各オペレーションに、実際の数値を記録する。
- クエリ実行プロセスの詳細な説明を返す。
EXPLAIN ANALYZEが提供するデータは?
オペレーションの実際の実行時間:
Actual Start Time: オペレーションが始まった時刻。Actual End Time: オペレーションが終わった時刻。
処理された行の合計数:
これでプランの予想(rowsの値)がどれくらい正確か分かる。
バッファ情報:
ディスクやメモリのバッファがどう使われたか。
EXPLAIN ANALYZEの使い方例
具体的な例を見てみよう。studentsという、学生データを持つテーブルがあるとする:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INTEGER,
grade FLOAT
);
INSERT INTO students (name, age, grade)
VALUES
('Alice', 22, 4.1),
('Bob', 19, 3.8),
('Charlie', 23, 4.5),
('Diana', 20, 3.9);
20歳より上の学生を抽出するクエリを実行してみる:
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20;
結果の例:
Seq Scan on students (cost=0.00..14.00 rows=2 width=116) (actual time=0.025..0.026 rows=2 loops=1)
Filter: (age > 20)
Rows Removed by Filter: 2
Planning Time: 0.032 ms
Execution Time: 0.048 ms
この結果を分解してみよう:
Seq Scan– PostgreSQLがテーブルをシーケンシャルスキャンしてるってこと。cost=0.00..14.00– これはオペレーションの予想コスト。rows=2– PostgreSQLは2行返すと予想してて(実際その通り!)。actual time=0.025..0.026– オペレーションの実際の実行時間(ミリ秒単位)。Rows Removed by Filter: 2– 2行がWHERE条件に合わなくてフィルタされた。
理論と実践の比較
ここがEXPLAIN ANALYZEの魔法:クエリが実際にどう実行されたかを見せてくれて、理論上の実行プランと比較できる。
もうちょい複雑な例を見てみよう。
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20 AND grade > 4.0;
結果の例:
Seq Scan on students (cost=0.00..14.00 rows=1 width=116) (actual time=0.026..0.027 rows=1 loops=1)
Filter: ((age > 20) AND (grade > 4.0))
Rows Removed by Filter: 3
Planning Time: 0.035 ms
Execution Time: 0.057 ms
何が分かるか:
- PostgreSQLは0.057ミリ秒でクエリを実行した。
- 条件
WHEREに合うのは1行だけ(rows=1)。 - 3行がフィルタで除外された(
Rows Removed by Filter: 3)。
まとめ
EXPLAIN ANALYZEを使うと、ボトルネックを見つけたり、クエリの最適化方法が分かる。たとえば:
Seq Scanが重すぎるなら、インデックスを追加するタイミングかも。- PostgreSQLの予想と実データが大きく違うなら、テーブルの統計情報(
ANALYZE)やインデックス構造を見直そう。
GO TO FULL VERSION