CodeGym /コース /SQL SELF /EXPLAIN ANALYZEを使ってクエリの実際の実行時間を測定する方法

EXPLAIN ANALYZEを使ってクエリの実際の実行時間を測定する方法

SQL SELF
レベル 41, レッスン 3
使用可能

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

何が分かるか:

  1. PostgreSQLは0.057ミリ秒でクエリを実行した。
  2. 条件WHEREに合うのは1行だけ(rows=1)。
  3. 3行がフィルタで除外された(Rows Removed by Filter: 3)。

まとめ

EXPLAIN ANALYZEを使うと、ボトルネックを見つけたり、クエリの最適化方法が分かる。たとえば:

  • Seq Scanが重すぎるなら、インデックスを追加するタイミングかも。
  • PostgreSQLの予想と実データが大きく違うなら、テーブルの統計情報(ANALYZE)やインデックス構造を見直そう。
2
タスク
SQL SELF, レベル 41, レッスン 3
ロック未解除
フィルタリングとソートを伴うクエリ実行の分析
フィルタリングとソートを伴うクエリ実行の分析
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION