「ビットマップヒープスキャン」と「ビットマップインデックススキャン」を理解する


36

私の誤解を次の例で説明します。

基本を理解していませんでしたBitmap Heap Scan NodeSELECT customerid, username FROM customers WHERE customerid < 1000 AND username <'user100';計画がこれであるクエリを検討してください。

Bitmap Heap Scan on customers  (cost=25.76..61.62 rows=10 width=13) (actual time=0.077..0.077 rows=2 loops=1)
  Recheck Cond: (((username)::text < 'user100'::text) AND (customerid < 1000))
  ->  BitmapAnd  (cost=25.76..25.76 rows=10 width=0) (actual time=0.073..0.073 rows=0 loops=1)
        ->  Bitmap Index Scan on ix_cust_username  (cost=0.00..5.75 rows=200 width=0) (actual time=0.006..0.006 rows=2 loops=1)
              Index Cond: ((username)::text < 'user100'::text)
        ->  Bitmap Index Scan on customers_pkey  (cost=0.00..19.75 rows=1000 width=0) (actual time=0.065..0.065 rows=999 loops=1)
              Index Cond: (customerid < 1000)

このノードの私の理解

そこに説明されているようbitmap heap scanテーブルブロックを順番に読み取ります。そのため、justを実行するときに発生するランダムテーブルアクセスのオーバーヘッドは発生しませんIndex Scan

後にIndex Scan行われた、PostgreSQLは不必要な避けるために、最適な行をフェッチする方法を知らないheap blocks reads(またはhitsホットキャッシュが存在する場合)。だからそれを理解するために、それは私の場合はインデックスの2つのビットマップを生成して実行することによって生成されているBitmap Index Scanと呼ばれる構造体()をbitmap生成しますBITWISE AND。ビットマップが生成されたため、不要なを避けて、テーブルを順番に最適に読み取ることができるようになりましたheap I/O-operations

それは多くの質問が来る場所です。

質問:ビットマップだけがあります。PostgreSQLは、ビットマップだけで行の物理的順序をどのように認識していますか?または、ビットマップを生成して、その要素をページへのポインターに簡単にマップできるようにしますか?もしそうなら、それはすべてを説明しますが、それはちょうど私の推測です。

だから、単純bitmap heap scan -> bitmap index scanにテーブルの適切な部分だけのシーケンシャルスキャンのようなものだと言えますか?


私はここで、このうちのいくつかの説明を書いた:stackoverflow.com/q/33100637/398670
クレイグリンガー

@CraigRinger理解できなかったことを正しく説明できなかったようです。もちろん、説明したように、PostgreSQLがテーブルを順番に読み取るためのビットマップがあります。特定のビットマップなどで指定された実際のブロックをどのように把握できるかわかりません001001010101011010101。または、実際には問題ではなく、ビットマップのブロックを非常に高速に見つけることができるということだけを知っている必要があります...?
St.Antario

ああ、ここで「ビットマップ」の意味を誤解しているかもしれません。編集でフォローアップさせてください。
クレイグリンガー

@CraigRingerたぶん、そこから定義を取りました。
-St.Antario

回答:


52

PostgreSQLは、ビットマップによって行の物理的な順序についてどのように知るのですか?

ビットマップは、ヒープページごとに1ビットです。ビットマップインデックススキャンは、インデックスエントリが指すヒープページアドレスに基づいてビットを設定します。

そのため、ビットマップヒープスキャンを実行する場合、線形テーブルスキャンを実行し、ビットマップを読み取って特定のページに煩わされるべきか、それともシークする必要があるかを確認します。

または、ビットマップを生成して、その要素をページへのポインターに簡単にマップできるようにしますか?

いいえ、ビットマップはヒープページに1:1で対応しています。

ここでこれについてもう少し書きました


OK、この文脈で「ビットマップ」の意味を誤解しているように見えます。

ヒープページごと、インデックスの読み取りごとなどに作成される "101011"のようなビット文字列ではありません。

ビットマップ全体は、スキャンされるリレーションのヒープページと同数のビットを持つ単一ビット配列です。

最初のインデックススキャンによって、すべてのエントリ0(false)から始まる1つのビットマップが作成されます。検索条件に一致するインデックスエントリが見つかると、そのインデックスエントリが指すヒープアドレスがビットマップへのオフセットとして検索され、そのビットが1(true)に設定されます。したがって、ビットマップインデックススキャンは、ヒープページを直接検索するのではなく、ビットマップ内の対応するビット位置を検索します。

2番目以降のビットマップインデックススキャンは、他のインデックスとそれらの検索条件で同じことを行います。

次に、各ビットマップがANDされます。結果のビットマップは、各ヒープページごとに1ビットを持ちます。ビットは、個々のビットマップインデックススキャンすべて、つまり、すべてのインデックススキャンで一致した検索条件で真である場合にのみ真になります。これらは、ロードして調べるためにわざわざ必要な唯一のヒープページです。各ヒープページには複数の行が含まれている可能性があるため、各行を調べて、すべての条件に一致するかどうかを確認する必要があります。これが "recheck cond"部分の目的です。

これらすべてを理解するために重要なことの1つは、インデックスエントリのタプルアドレスctidが、ヒープページ番号とヒープページ内のオフセットの組み合わせである行のを指していることです。ビットマップインデックススキャンは、とにかくページ全体をチェックするため、オフセットを無視し、そのページのいずれかの行が条件に一致する場合にビットを設定します。


グラフィカルな例

Heap, one square = one page:
+---------------------------------------------+
|c____u_____X___u___X_________u___cXcc______u_|
+---------------------------------------------+
Rows marked c match customers pkey condition.
Rows marked u match username condition.
Rows marked X match both conditions.


Bitmap scan from customers_pkey:
+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
+---------------------------------------------+
One bit per heap page, in the same order as the heap
Bits 1 when condition matches, 0 if not

Bitmap scan from ix_cust_username:
+---------------------------------------------+
|000001000001000100010000000001000010000000010| bitmap 2
+---------------------------------------------+

ビットマップが作成されると、ビット単位のANDが実行されます:

+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
|000001000001000100010000000001000010000000010| bitmap 2
 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|000000000001000000010000000000000010000000000| Combined bitmap
+-----------+-------+--------------+----------+
            |       |              |
            v       v              v
Used to scan the heap only for matching pages:
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+

ビットマップヒープスキャンは、各ページの先頭をシークし、ページを読み取ります。

+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
seek------->^seek-->^seek--------->^
            |       |              |
            ------------------------
            only these pages read

ページごとに1行を超えることがあり、必ずしもすべてが条件に一致するわけではないため、各読み取りページは条件に対して再チェックされます。


ああ、それは彼らがによって意味したものだ移入ビットマップを。
St.Antario

@ St.Antario説明するためにグラフィックを追加しました
クレイグリンガー

ビットマップスキャンについてもう1つ明確にしましょう。ヒープページに1:1のビットマップがあり、ビットマップのビットインデックスによってヒープページを決定できるとおっしゃいました。リレーションにはディスク上のページが順番に並んでいない(クラスター化されていない)ため、ビットマップのオフセットだけでページのアドレスを決定する方法は明確ではありません。プランナーは、特定の関係のオフセットによってページアドレスを計算する方法を知っていると思います。本当?
St.Antario

1
そのため、ドライブにあるすべてのページを配置する必要があります。さらに、リレーションのデータは2つ以上のドライブに分散される可能性があるため(リレーションのページの線形順序を想像するのは困難です)、次のページの実際のオフセットを決定することは困難です。「オフセット」とは、ドライブ上の物理的な位置に対応する実際の物理的なオフセットを意味すると考えているためです。
St.Antario

2
PostgreSQLは、ドライブについてはほとんど気にしません。ファイルシステムのファイルだけを気にします。リレーションの論理ファイルは線形で連続しており、それがビットマップの終わりです。(ファイルには複数のエクステントが存在する場合がありますが、それらは連続して追加されているかのように扱われ、ビットマップはそれらのすべての上にあります)。あなたは間違った抽象化レベルを見ています。(補足として、ビットマップインデックススキャンのビットマップはプランナーによって計算されず、btreeインデックスアクセスメソッドの一部であり、プランナーよりもエグゼキューターに関連しています)。
クレイグリンガー

3

PostgreSQLでのビットマップスキャンの詳細については、ブログ投稿 https://rajeevrastogi.blogspot.in/2018/02/bitmap-scan-in-postgresql.html?showComment=1518410565792#c4647352762092142586を参照してください。

ビットマップスキャンの全体的なクイック機能の概要:

  1. ビットマップヒープスキャンは、ビットマップインデックススキャンからタプルを要求します。

  2. ビットマップインデックススキャンは、通常のインデックススキャンとほぼ同じ方法で、条件に従ってインデックスをスキャンします。ただし、ヒープデータに対応するTID(ページ番号とその中のオフセットで構成される)を返す代わりに、それらのTIDをビットマップに追加します。簡単に理解するために、このビットマップにはすべてのページのハッシュ(ページ番号に基づいてハッシュ)が含まれ、各ページエントリにはそのページ内のすべてのオフセットの配列が含まれると考えることができます。

  3. 次に、ビットマップヒープスキャンはビットマップを読み取り、保存されているページ番号とオフセットに対応するヒープデータを取得します。次に、可視性、資格などをチェックし、これらすべてのチェックの結果に基づいてタプルを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.