帶有點陣圖索引掃描的查詢計劃中的“重新檢查條件:”行
這是對上一個問題的評論的衍生:
**
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
輸出中學到什麼?
一點調查似乎表明重新檢查條件總是列印在 中
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:
此外,當使用
BUFFERS
option:執行時,EXPLAIN (ANALYZE, BUFFERS) ...
添加了另一行,如:Buffers: shared hit=279 read=79
這表明有多少基礎表(和索引)是從記憶體中讀取的(
shared hit=279
)以及必須從磁碟中獲取多少(read=79
)。如果您重複查詢,對於不太大的查詢,“讀取”部分通常會消失,因為在第一次呼叫之後現在所有內容都被記憶體了。第一個呼叫告訴您已經記憶體了多少。隨後的呼叫顯示您的記憶體可以處理多少(目前)。還有更多選擇。關於
BUFFERS
選項的手冊:具體來說,包括命中、讀取、弄髒和寫入的共享塊的數量,命中、讀取、弄髒和寫入的本地塊的數量,以及讀取和寫入的臨時塊的數量。
繼續閱讀,還有更多。
這是原始碼中的輸出選項列表。