このコマンドはPostgreSQLプランナが提供された問い合わせ文用に生成する実行計画を表示します。 この実行計画は、この文によって参照されるテーブル(複数の場合もあり)がスキャンされる方法(単純なシーケンススキャン、インデックススキャン、など)を示したり、複数のテーブルが参照される場合にはそれぞれの入力テーブルに必要な行を組み合わすために使用される結合アルゴリズムを示したりします。
この表示で最も重要なのは、文の実行にかかるコストの見積もりです。 コストとは、プランナが推定する、文の実行にかかる時間(ディスクページ抽出の単位で計測)です。 実際には2つの数が表示されます。 最初の行が返される前のスタートアップ時間、そして全ての行が返されるまでの合計の時間です。 ほとんどの問い合わせにとって問題となるのは合計時間ですが、EXISTS副問い合わせなどのコンテキストでは、プランナは最も短い合計時間ではなく最も短いスタートアップ時間を選びます(エクゼキュータは行を1つ取得した後に停止するからです)。 更に、もしLIMIT句で返す行数を制限する場合、プランナはどの計画が一番低コストになるかを概算するため処理の終点までの間で適切な補間を行ないます。
ANALYZEオプションにより、文は計画だけではなく実際に実行されます。 各計画ノードにて費やされた総経過時間(ミリ秒単位)と実際に返される行数が表示に追加されます。 プランナの推測と実際の値がどれだけ近いかを確認できるという点でこのオプションは有用なものです。
重要項目: ANALYZEを使用した場合は、文が実際に実行されることを忘れないでください。 EXPLAINはSELECTが返すはずの出力を全く表示しませんが、文の副作用は通常通り発生します。 INSERT、UPDATE、DELETE、EXECUTE文に対してEXPLAIN ANALYZEをデータに影響が出ないように使用したい場合は、以下の方法を使用してください。
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
コマンドを実行し、実際の稼働時間を表示します。
要約だけではなく計画ツリーの内部表現を全て表示します。 通常、このオプションは特殊なのデバッグ目的のためだけに有用です。 VERBOSEの出力は、explain_pretty_print設定パラメータの設定次第で印刷に適した形にすることもできます。
実行計画の表示対象となる、任意のSELECT、INSERT、UPDATE、DELETE、EXECUTE、もしくはDECLARE文です。
PostgreSQLのオプティマイザにおけるコスト情報の使用に関する文書は多くありません。 更に詳しい情報については、項13.1を参照してください。
PostgreSQL問い合わせプランナが問い合わせの最適化の際に十分に情報を持った決定ができるようにするために、ANALYZE文を実行して、テーブル内のデータの分布についての統計情報を記録させなければなりません。 これを行わない場合(、あるいは、前回ANALYZEを実行した後、テーブル内のデータの統計的分布が大幅に変わった時)、推定コストは問い合わせの実際の属性とは適合することはなく、その結果、劣った問い合わせ計画が選択されることになります。
PostgreSQL 7.3より前のバージョンでは、問い合わせ計画はNOTICEメッセージという形式で通知されていました。 現在では、問い合わせ計画は問い合わせ結果(単一のテキスト列から成るテーブルの形式で)として表示されます。
一つのinteger列と10000行を持つテーブル上の単純な問い合わせの問い合わせ計画を表示します。
EXPLAIN SELECT * FROM foo; QUERY PLAN --------------------------------------------------------- Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4) (1 row)
インデックスがある場合、インデックス付けが可能なWHERE条件を持つ問い合わせを使用すると、EXPLAINは異なる計画を表示します。
EXPLAIN SELECT * FROM foo WHERE i = 4; QUERY PLAN -------------------------------------------------------------- Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4) Index Cond: (i = 4) (2 rows)
集約関数を使用した問い合わせに対する問い合わせ計画の例を示します。
EXPLAIN SELECT sum(i) FROM foo WHERE i < 10; QUERY PLAN --------------------------------------------------------------------- Aggregate (cost=23.93..23.93 rows=1 width=4) -> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4) Index Cond: (i < 10) (3 rows)
以下はEXPLAIN EXECUTEを使用して準備された問い合わせに対する実行計画を表示する例です。
PREPARE query(int, int) AS SELECT sum(bar) FROM test WHERE id > $1 AND id < $2 GROUP BY foo; EXPLAIN ANALYZE EXECUTE query(100, 200); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.66..0.67 rows=7 loops=1) -> Index Scan using test_pkey on test (cost=0.00..32.97 rows=1311 width=8) (actual time=0.05..0.39 rows=99 loops=1) Index Cond: ((id > $1) AND (id < $2)) Total runtime: 0.85 msec (4 rows)
もちろん、ここで示した具体的な数値は対象とするテーブルの実際の中身によって変わります。 また、この数値や選択された問い合わせ戦略は、プランナの改良のためにPostgreSQLのリリース間で異なることもありますので注意してください。 更に、ANALYZEコマンドは、データの統計情報を推定する際にランダムなサンプリングを行いますので、実際のテーブル内の分布が変わっていなくても、新しくANALYZEを実行した後に推定コストが変わることがあります。