これは、前の質問へのコメントからのスピンオフです。
PostgreSQL 9.4を使用すると、EXPLAIN
によって出力されたクエリプランでビットマップインデックスがスキャンされた後、常にRecheck Cond:
行が表示されます。
参照された質問のEXPLAIN
出力のように:
-> Bitmap Heap Scan on table_three (cost=2446.92..19686.74 rows=8159 width=7) Recheck Cond: (("timestamp" > (now() - '30 days'::interval)) AND (client_id > 0)) -> BitmapAnd (cost=2446.92..2446.92 rows=8159 width=0) -> Bitmap Index Scan on table_one_timestamp_idx (cost=0.00..1040.00 rows=79941 width=0) Index Cond: ("timestamp" > (now() - '30 days'::interval)) -> Bitmap Index Scan on fki_table_three_client_id (cost=0.00..1406.05 rows=107978 width=0) Index Cond: (client_id > 0)
またはEXPLAIN ANALYZE
の出力で、シンプルで巨大なテーブル(work_mem
がほとんどない)の場合:
EXPLAIN ANALYZE SELECT * FROM aa WHERE a BETWEEN 100000 AND 200000;
Bitmap Heap Scan on aa (cost=107.68..4818.05 rows=5000 width=4) (actual time=27.629..213.606 rows=100001 loops=1) Recheck Cond: ((a >= 100000) AND (a <= 200000)) Rows Removed by Index Recheck: 758222 Heap Blocks: exact=693 lossy=3732 -> Bitmap Index Scan on aai (cost=0.00..106.43 rows=5000 width=0) (actual time=27.265..27.265 rows=100001 loops=1) Index Cond: ((a >= 100000) AND (a <= 200000))
これは、ビットマップインデックススキャン後にもう一度インデックス条件をチェックする必要があることを意味しますか?EXPLAIN
の出力から他に何を学ぶことができますか?
として @ Chrisは参照された質問に正しくコメントしました :
少し調べたところ、再チェック条件は常に
EXPLAIN
に出力されているようですが、実際には、_work_mem
_がビットマップに損失が生じるほど小さい場合にのみ実行されます。考え? http://www.postgresql.org/message-id/[email protected]
これはすべて真実であり、コア開発者のHeikki Linnakangasは一流のソースですが、この投稿は2007年に遡ります(Postgres 8.2)。これは Postgres 9.4の詳細な説明を含むMichael Paquierによるブログ投稿 です。ここで、_EXPLAIN ANALYZE
_の出力は、より多くの情報で改善されています。
_Recheck Cond:
_行は、ビットマップインデックススキャン用にalwaysです。基本的な EXPLAIN
の出力では、それ以上はわかりません。質問の2番目の引用にあるように、_EXPLAIN ANALYZE
_から追加情報を取得します。
_Heap Blocks: exact=693 lossy=3732
_
合計4425個のデータページ(ブロック)から、693個の保存されたタプル正確に(タプルポインターを含む) 、他の3732ページはビットマップでlossy(データページのみ)でした。これは、_work_mem
_が、インデックススキャンから構築されたビットマップ全体を正確に格納するのに十分でない場合に発生します(可逆)。
ビットマップはフェッチするページのみを記憶し、ページ上の正確なタプルは記憶しないため、非可逆共有からのページについてインデックス条件を再チェックする必要があります。ページ上のすべてのタプルが必ずしもインデックス条件を渡すわけではありません。実際に実際に条件を再確認する必要があります。
これは 新しい追加が議論されたpgsqlハッカーのスレッド です。著者 藤田悦朗が公式を提供 損失のあるビットマップエントリとそれに続く条件の再チェックを回避するための最小_work_mem
_の計算方法。複数のビットマップスキャンを使用する複雑なケースでは、計算は信頼できないため、EXPLAIN
からの実際の数値の出力には使用されませんでした。それでも、単純なケースの推定値として使用できます。
BUFFERS:
_さらに、BUFFERS
オプションを指定して実行すると、EXPLAIN (ANALYZE, BUFFERS) ...
のように別の行が追加されます。
_Buffers: shared hit=279 read=79
_
これは、基になるテーブル(およびインデックス)のどれだけがキャッシュから読み取られたか(_shared hit=279
_)およびディスクからフェッチする必要があった量(_read=79
_)を示します。クエリを繰り返すと、あまり大きくないクエリの場合、通常は「読み取り」部分が消えます。これは、最初の呼び出し後にすべてがキャッシュされるためです。最初の呼び出しは、すでにキャッシュされている量を示します。後続の呼び出しは、キャッシュが(現在)処理できる量を示します。
より多くのオプションがあります。 BUFFERS
オプションに関するマニュアル:
具体的には、ヒット、読み取り、ダーティ、書き込みされた共有ブロックの数、ヒット、読み取り、ダーティ、書き込みされたローカルブロックの数、読み取りおよび書き込みされた一時ブロックの数を含めます。
続きを読む、もっとあります。
ソースコード の出力オプションのリストを次に示します。
アーウィン、これは以前からのコメントスレッドでの議論だったので、もう少し突っ込むことにしました...
適切なサイズのテーブルからの非常に単純なクエリがあります。通常、十分なwork_mem
がありますが、この場合、コマンドを使用しました
SET work_mem = 64;
非常に小さいwork_mem
を設定し、
SET work_mem = default;
work_mem
をクエリに十分な大きさに設定します。
したがって、EXPLAIN
のみでクエリを実行すると、
EXPLAIN
SELECT * FROM olap.reading_facts
WHERE meter < 20;
低と高の両方の結果を取得しましたwork_mem
:
低work_mem
Bitmap Heap Scan on reading_facts (cost=898.92..85632.60 rows=47804 width=32)
Recheck Cond: (meter < 20)
-> Bitmap Index Scan on idx_meter_reading_facts (cost=0.00..886.96 rows=47804 width=0)
Index Cond: (meter < 20)
高work_mem
Bitmap Heap Scan on reading_facts (cost=898.92..85632.60 rows=47804 width=32)
Recheck Cond: (meter < 20)
-> Bitmap Index Scan on idx_meter_reading_facts (cost=0.00..886.96 rows=47804 width=0)
Index Cond: (meter < 20)
要するに、EXPLAIN
の場合のみ、予想どおり、クエリプランは再チェック条件が可能であることを示していますが、実際に計算されるかどうかはわかりません。
クエリにANALYZE
を含めると、結果から知る必要のある情報がわかります。
低work_mem
Bitmap Heap Scan on reading_facts (cost=898.92..85632.60 rows=47804 width=32) (actual time=3.130..13.946 rows=51840 loops=1)
Recheck Cond: (meter < 20)
Rows Removed by Index Recheck: 86727
Heap Blocks: exact=598 lossy=836
-> Bitmap Index Scan on idx_meter_reading_facts (cost=0.00..886.96 rows=47804 width=0) (actual time=3.066..3.066 rows=51840 loops=1)
Index Cond: (meter < 20)
高work_mem
Bitmap Heap Scan on reading_facts (cost=898.92..85632.60 rows=47804 width=32) (actual time=2.647..7.247 rows=51840 loops=1)
Recheck Cond: (meter < 20)
Heap Blocks: exact=1434
-> Bitmap Index Scan on idx_meter_reading_facts (cost=0.00..886.96 rows=47804 width=0) (actual time=2.496..2.496 rows=51840 loops=1)
Index Cond: (meter < 20)
繰り返しになりますが、予想どおり、ANALYZE
を含めると、いくつかの非常に重要な情報がわかります。低い[work_mem
]の場合、インデックスの再チェックによって削除された行があり、lossy
ヒープブロックがあることがわかります。
残念ながら、それだけではEXPLAIN
は不十分ですインデックスの再チェックが実際に行われるかどうかを知るには一部の行IDはビットマップヒープスキャン中にページを保持するために削除されるため、必要です。
中程度の長さのクエリの問題を診断するにはEXPLAIN ANALYZE
を使用すると問題ありませんが、クエリの完了に非常に長い時間がかかる場合は、EXPLAIN ANALYZE
を実行してビットマップインデックスが損失に変換されていることを検出しますwork_mem
が不十分なため、まだ難しい制約です。テーブル統計からこの発生の可能性をEXPLAIN
に推定させる方法があったらいいのにと思います。