Postgresql

帶有點陣圖索引掃描的查詢計劃中的“重新檢查條件:”行

  • May 1, 2021

這是對上一個問題的評論的衍生:

**Recheck Cond:**使用 PostgreSQL 9.4,在查詢計劃輸出的點陣圖索引掃描之後似乎總是有一行EXPLAIN

就像在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/464F3C5D.2000700@enterprisedb.com

雖然這一切都是真的,核心開發人員 Heikki Linnakangas 是一流的資源,但這篇文章可以追溯到 2007 年(Postgres 8.2)。這是Michael Paquier 的一篇部落格文章,其中詳細解釋了 Postgres 9.4,其中的輸出EXPLAIN ANALYZE已通過更多資訊得到改進。

Recheck Cond:始終用於點陣圖索引掃描。basic 的輸出EXPLAIN不會告訴我們更多資訊。我們從EXPLAIN ANALYZE問題的第二個引用中可以看到更多資訊:

Heap Blocks: exact=693 lossy=3732

在總共 4425 個數據頁(塊)中,有 693 個完全儲存元組(包括元組指針),而其他 3732 個頁在點陣圖中是有損的(只是數據頁)。當work_mem不足以儲存從索引掃描建構的整個點陣圖時,就會發生這種情況(無損)。

對於有損共享中的頁面,必須重新檢查索引條件,因為點陣圖只記住要獲取的頁面,而不是頁面上的確切元組。並非頁面上的所有元組都一定會通過索引條件,有必要實際重新檢查條件。

這是pgsql 黑客上討論新增內容的執行緒。作者Etsuro Fujita 提供了一個公式,用於計算最小值work_mem以避免有損點陣圖條目和隨後的條件重新檢查。對於具有多個點陣圖掃描的複雜情況,該計算不可靠,因此它不用於從EXPLAIN. 它仍然可以作為簡單案例的估計。

附加線BUFFERS:

此外,當使用BUFFERSoption:執行時,EXPLAIN (ANALYZE, BUFFERS) ...添加了另一行,如:

Buffers: shared hit=279 read=79

這表明有多少基礎表(和索引)是從記憶體中讀取的(shared hit=279)以及必須從磁碟中獲取多少(read=79)。如果您重複查詢,對於不太大的查詢,“讀取”部分通常會消失,因為在第一次呼叫之後現在所有內容都被記憶體了。第一個呼叫告訴您已經記憶體了多少。隨後的呼叫顯示您的記憶體可以處理多少(目前)。

還有更多選擇。關於BUFFERS選項的手冊:

具體來說,包括命中、讀取、弄髒和寫入的共享塊的數量,命中、讀取、弄髒和寫入的本地塊的數量,以及讀取和寫入的臨時塊的數量。

繼續閱讀,還有更多。

這是原始碼中的輸出選項列表。

引用自:https://dba.stackexchange.com/questions/106264