実行計画の処理


インデックスとテーブルへのアクセス

Seq Scan

Seq Scanは、ディスクに保存されている通り (TABLE ACCESS FULLのように)に関係(テーブル)をスキャンします。

Index Scan

Index ScanはBツリー走査を行い、 一致する全ての値を検索するのにリーフノードをたどり、 対応するテーブル上のデータを取り出します。 INDEX RANGE SCANに続いてTABLE ACCESS BY INDEX ROWIDを 行うのに似ています。第1章, 「 SQLインデックスの内部構造も参照して下さい。

いわゆるインデックスフィルタ述語は、Index Scanの パフォーマンス問題を引き起こします。次の節でその問題の 識別方法を説明しています。

Index Only Scan (PostgreSQL 9.2以降)

Index Only ScanはBツリー走査を行い、 一致する全ての値を検索するのにリーフノードをたどります。 結果を返すのに必要な列が全てインデックスに含まれているので、 テーブルアクセスは不要です(例外としてMVCCのvisibility informationがあります)。 「インデックスのみのスキャン: テーブルアクセスを 避ける」も参照して下さい。

Bitmap Index Scan / Bitmap Heap Scan / Recheck Cond

Tom Lane氏のPostgreSQLの パフォーマンスに関するメーリングリストへの投稿が 非常に分かりやすく簡潔です。

プレーンなIndex Scanは、一度に 1つのタプルへのポインタをインデックスから取り出し、 テーブル内のそのタプルにすぐアクセスします。 ビットマップスキャンは、一度に全てのタプルへのポインタを インデックスから取り出し、インメモリな「ビットマップ」データ構造を 使ってソートし、物理的なタプル位置の順にテーブルのタプルに アクセスします。

このウェブサイトにぴったりのカップは僕たちのショップにあります。
#見た目もいい感じだし、ここでの僕の仕事を支えてくれています

結合処理

通常、結合処理で同時に処理できるのは2テーブルまでです。 1つのクエリにそれ以上の結合対象のテーブルがある場合、 まず2つのテーブルを結合し、それからその中間結果を次のテーブルと 結合するというように、順番に処理されます。結合の話をする場合には、 「テーブル」という言葉は「中間結果」の事を指す場合もあるのです。

Nested Loops

片方のテーブルから結果を取り出し、その結果をもう1つの テーブルの各行に対して問い合わせて、2つのテーブルを結合します。 「入れ子ループ」も参照して下さい。

Hash Join / Hash

ハッシュ結合では、結合の片方から候補となるレコードを ハッシュテーブル(実行計画でHashとマークされます)にロードし、 それを結合のもう片方の各行と突き合わせます。「ハッシュ結合」も参照して下さい。

Merge Join

(ソート)マージ結合は、並べ替えられた2つのリストをジッパーのように マージします。結合の両辺は事前にソートしておく必要があります。 「ソートマージ」も参照して下さい。

ソートとグルーピング

Sort / Sort Key

Sort Keyにある列で結果セットをソートします。 Sortの処理は、中間結果(パイプライン化されていないもの)を マテリアライズするために、非常に多くのメモリを必要とします。 「インデックスを使ったorder by」も参照して下さい。

GroupAggregate

group by句に従って、並べ替え済みの 結果セットをまとめます。この処理は中間結果をバッファせず、 パイプライン化して実行します。「インデックスを使ったgroup by」も参照して下さい。

HashAggregate

レコードをグルーピングするのに一時的なハッシュテーブルを使います。 HashAggregate処理では、データセットは事前に ソートされている必要はありませんが、 中間結果(パイプライン化されていないもの)をマテリアライズするために 非常に多くのメモリを必要とします。出力は、 一定のルールに沿って並べられているわけではないものになります。 「インデックスを使ったgroup by」も参照して下さい。

最初のN件のみを選択するクエリ

Limit

必要な行数が取り出せた時点で、内部的な処理を中断します。 「最初のN行のみの選択」も参照して下さい。

最初のN件のみを選択するクエリの効率は、 内部で動作する処理の実行モードに依存します。Sortのような、 パイプライン化されていない処理を途中で中断する動作の時は、 非常に非効率になります。

WindowAgg

窓関数の使用を表します。 「効率的な ページネーションのための窓関数の使用」も参照して下さい。

注意

PostgreSQLでは、窓関数の使用時には最初のN件のみを取得するクエリは パイプライン化して実行できません。

Photo of Markus Winand
Markus Winand氏は、開発者がSQLパフォーマンスを改善するお手伝いをしています。 彼は、SQL Performance Explainedの 著者でもあり、出張トレーニングhttp://winand.at/での リモート講義も 行っています。