Tuple含義
- 作用
PG并沒有像Oracle那樣的undo來存放舊數據,而且PG沒有真正意義上的delete,而是將舊版本直接存放于relation文件中,也就是成為了dead tuple。我們可以理解成“過期的數據” - 含義
tuple就相當于一個存儲數據的小容器,它包含了兩個及以上的components。可能會與Oracle中的row類似,但是這二者之間并不能劃等號。 - 結構
+---------------------+---------------+----------------+| HeapTupleHeaderData | nulls bitmap | padding |+------------+--------+---------------+----------------+| object ID | value1 value2 value3 ... |+------------+-----------------------------------------+
(1) HeapTupleHeaderData
(2)nulls bitmap
這是個可選項,當t_infomask有HEAP_HASNULL標志的話,這個數組就會有值
(3) padding
前面null bitmap的長度不確定,為了后面數據能對齊,這里對HeapTupleHeaderData+nulls bitmap 字節對齊,這里會有留空。
(4) OID值,這是個可選項,當t_infomask有HEAP_HASOID_OLD時,會有此值
(5)用戶數據,就是各列的數據;
Tuple的實踐
主要函數為如下五個:
step1. ExecInsert
step2. ExecMaterializeSlot
step3. ExecCopySlotTuple——拼裝入口
step4. heap_form_tuple——根據values和isnull拼裝tuple
step5. heap_fill_tuple——根據desc把數據填到正確的位置
執行器會把tuple包裝成tuple table slot來處理,相當于給HeapTuple包裝了一層:TupleTableSlots
代碼里會見到很多tts = TupleTableSlots,結構如下:
typedef struct TupleTableSlot
{NodeTag type;bool tts_isempty; /* true = slot is empty */bool tts_shouldFree; /* should pfree tts_tuple? */bool tts_shouldFreeMin; /* should pfree tts_mintuple? */bool tts_slow; /* saved state for slot_deform_tuple */HeapTuple tts_tuple; /* physical tuple, or NULL if virtual */TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */MemoryContext tts_mcxt; /* slot itself is in this context */Buffer tts_buffer; /* tuple's buffer, or InvalidBuffer */int tts_nvalid; /* # of valid values in tts_values */Datum *tts_values; /* current per-attribute values */bool *tts_isnull; /* current per-attribute isnull flags */MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */long tts_off; /* saved state for slot_deform_tuple */
} TupleTableSlot;
于普通tuple來說,ExecInsert的第一件事就是“物化”Tuple Slot:
【slot】 ----組裝----> 【materialized slot】