Postgresql
PostgreSQL Index Only Scan 不能返回 ctid
我在 PostgreSQL 11 中有這張表:
CREATE TABLE A (id bigint PRIMARY KEY, text text)
現在我想獲取
ctid
滿足某些條件的行,例如id = 123
.然而,即使
pg_hint_plan
用來提示 PostgreSQL 使用Index Only Scan,它也總會給我Index Scan:/*+ IndexOnlyScan(a) */ explain analyze select ctid from a where id = 823977776533426178; QUERY PLAN ---------------------------------------------------------------------------------------------------------- Index Scan using a_pkey on a (cost=0.14..8.16 rows=1 width=6) (actual time=0.038..0.039 rows=1 loops=1) Index Cond: (id = '823977776533426178'::bigint) Planning Time: 0.122 ms Execution Time: 0.095 ms (4 rows)
我的理解是
ctid
每行的物理行ID(block_no:record_offset),它必須包含在任何btree索引中,因為它需要這些資訊來從堆文件中獲取行。那麼為什麼僅索引掃描不能
ctid
直接返回呢?只是PostgreSQL沒有那樣實現它嗎?
您的理解幾乎但並不完全正確。確實,每個 btree 索引元組都需要一個
ctid
(或某種形式的塊號和元組索引)來指向堆元組(表行)。但是(至少)自從 Postgres 8.3 引入“僅堆元組”以來,可能有一條HOT 鏈可以跟隨以到達快照中的目前活動元組 - 與儲存在索引中的元組不同。ctid
由於也不可能使用
ctid
(或任何系統列)作為索引表達式,因此目前(以及在可預見的將來)完全不可能ctid
從僅索引掃描中獲得 a 。有關的:
在 Index-only_scans / Interaction_with_HOT 上引用Postgres Wiki :
借助 HOT,索引掃描可以遍歷所謂的 HOT 鏈;它可以從物理索引元組(可能由原始 INSERT 創建,並且與邏輯元組的早期版本相關)到相應的物理堆元組。堆元組本身將包含指向元組的下一個版本(即元組 ctid)的指針,而後者又可能有自己的指針。索引掃描最終會根據查詢的快照到達目前的元組。