インデックスとテーブルへのアクセス
- Seq Scan
Seq Scan
は、ディスクに保存されている通り(TABLE ACCESS FULL
のように)に関係(テーブル)をスキャンします。- Index Scan
Index Scan
はBツリー走査を行い、 一致する全ての値を検索するのにリーフノードをたどり、対応するテーブル上のデータを取り出します。INDEX RANGE SCAN
に続いてTABLE ACCESS BY INDEX ROWID
を行うのに似ています。第1章1, 「 SQLインデックスの内部構造」も参照して下さい。いわゆるインデックスフィルタ述語は、
Index Scan
の パフォーマンス問題を引き起こします。次の節でその問題の 識別方法を説明しています。- Index Only Scan
Index Only Scan
はBツリー走査を行い、一致する全ての値を検索するのにリーフノードをたどります。 結果を返すのに必要な列が全てインデックスに含まれているので、 テーブルアクセスは不要です(例外としてMVCCのvisibility informationがあります)。「インデックスのみのスキャン: テーブルアクセスを 避ける」も参照して下さい。- Bitmap Index Scan / Bitmap Heap Scan / Recheck Cond
Tom Lane氏のPostgreSQLの パフォーマンスに関するメーリングリストへの投稿が非常に分かりやすく簡潔です。
プレーンな
Index Scan
は、一度に 1つのタプルへのポインタをインデックスから取り出し、テーブル内のそのタプルにすぐアクセスします。 ビットマップスキャンは、一度に全てのタプルへのポインタを インデックスから取り出し、インメモリな「ビットマップ」データ構造を 使ってソートし、物理的なタプル位置の順にテーブルのタプルにアクセスします。— Tom Lane
協力してください
この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。
結合処理
通常、結合処理で同時に処理できるのは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 15以降でのRun Conditionは、最初のN行のみの取得で停止する可能性を表します。「効率的なページネーションのための窓関数の使用」も参照して下さい。