1.表和索引所使用的頁面格式的概述
項指的是存儲在一個頁面裏的獨立數據值。在一個表裏,一個項是一個行;在一個索引裏,一個項是一條索引記錄。
每個表和索引都以固定尺寸(通常是 8K ,但也可以在編譯時選擇其它尺寸)的頁面數組存儲。在表裏,所有頁面邏輯上都相同,所以一個特定的項(行)可以存儲在任何頁面裏。
在索引裏,第一個頁面通常保留爲元頁面,保存着控制信息,並且依索引訪問方法的不同,在索引裏可能有不同類型的頁面。
2.一個頁面的整體佈局(5部分)
注意:高版本如10、11、12PageHederData是佔24個字節。
3.頁面5個部分的說明
3.1頁頭數據-PageHeaderData(20byte)
下面8.2版本的pageHeader結構圖:
下面9以上版本pageHeader結構圖:
8.2:
字段 | 類型 | 長度 | 描述 |
---|---|---|---|
pd_lsn | XLogRecPtr | 8 字節 | LSN: 最後修改這個頁面的 xlog 記錄最後一個字節後面第一個字節 |
pd_tli | TimeLineID | 4 字節 | 最後修改的 TLI |
pd_lower | LocationIndex | 2 字節 | 到自由空間開頭的偏移量 |
pd_upper | LocationIndex | 2 字節 | 到自由空間結尾的偏移量 |
pd_special | LocationIndex | 2 字節 | 到特殊空間開頭的偏移量 |
pd_pagesize_version | uint16 | 2 字節 | 頁面大小和佈局版本號信息 |
9以上:
Field | Type | Length | Description |
---|---|---|---|
pd_lsn | PageXLogRecPtr | 8 bytes | 記錄最後一次對頁修改的xlog記錄 |
pd_checksum | uint16 | 2 bytes | 頁面的校驗和,用於判斷當前頁是否完整 |
pd_flags | uint16 | 2 bytes | 指示當前頁的狀態 |
pd_lower | LocationIndex | 2 bytes | 本頁空閒位置的起始指針 |
pd_upper | LocationIndex | 2 bytes | 本業空閒位置的結束指針 |
pd_special | LocationIndex | 2 bytes | 頁預留的位置 |
pd_pagesize_version | uint16 | 2 bytes | 頁面大小和版本信息 |
pd_prune_xid | TransactionId | 4 bytes | 最後一次刪除或更新的xid |
3.2項指針數據、項標識符-ItemPointerData、ItemIdData(4byte)
說明:
1)在頁頭後面是項標識符(ItemIdData),每個需要四個字節。一個項標識符包含一個到項開頭的字節偏移量,它自己以字節計的長度,以及一套屬性位,這些屬性位影響它的解釋。新的項標識符根據需要從未分配空間的開頭分配。項標識符的數目可以通過查看 pd_lower 來判斷,在分配新標識符的時候會遞增。因爲一個項標識符在其釋放前絕對不會移動,所以它的索引可以用於長時間地引用一個項,即使該項本身因爲壓縮自由空間在頁面內部進行了移動也如此。實際上,PostgreSQL 創建的每個指向項的指針(ItemPointer ,也叫做 CTID)都由一個頁號和一個項標識符的索引組成。
3.3未分配的空間-FreeSpace
說明:
1)即該頁剩餘未分配空間;
2)新項指針從這個區域的開頭開始分配;
3)新項從結尾開始分配。
3.4實際項-Items
項本身存儲在從未分配空間末尾開始從後向前分配的空間裏。它們的實際結構因表包含的內容不同而不同。表和序列都使用一種叫做 HeapTupleHeaderData 的結構(8.2):
字段 | 類型 | 長度 | 描述 |
---|---|---|---|
t_xmin | TransactionId | 4 字節 | 插入 XID 戳記 |
t_cmin | CommandId | 4 字節 | 插入 CID 戳記 |
t_xmax | TransactionId | 4 字節 | 刪除 XID 戳記 |
t_cmax | CommandId | 4 字節 | 刪除 CID 戳記(與 t_xvac 重疊) |
t_xvac | TransactionId | 4 字節 | 用於移動行版本操作的 VACUUM 的 XID |
t_ctid | ItemPointerData | 6 字節 | 這個或者新行的當前 TID |
t_natts | int16 | 2 字節 | 字段數目 |
t_infomask | uint16 | 2 字節 | 各種標誌位 |
t_hoff | uint8 | 1 字節 | 到用戶數據的偏移量 |
9以上結構:
Field | Type | Length | Description |
---|---|---|---|
t_xmin | TransactionId | 4 bytes | insert XID stamp |
t_xmax | TransactionId | 4 bytes | delete XID stamp |
t_cid | CommandId | 4 bytes | insert and/or delete CID stamp (overlays with t_xvac) |
t_xvac | TransactionId | 4 bytes | XID for VACUUM operation moving a row version |
t_ctid | ItemPointerData | 6 bytes | current TID of this or newer row version |
t_infomask2 | uint16 | 2 bytes | number of attributes, plus various flag bits |
t_infomask | uint16 | 2 bytes | various flag bits |
t_hoff | uint8 | 1 byte | offset to user data |
說明:
1)所有錶行都用同樣方法構造。它們有一個定長的頭(在大多數機器上佔據 27 個字節),後面跟着一個可選的 null 位圖,一個可選的對象 ID 字段,以及用戶數據。頭在表52-4裏詳細描述。實際用戶數據(行的字段)從 t_hoff 標識的偏移量開始,它必須是該平臺的 MAXALIGN 距離的倍數。null 位圖只有在 t_infomask 裏面的 HEAP_HASNULL 位設置了的時候纔出現。如果它出現了,那麼它緊跟在定長頭後面,佔據足夠容納每個數據字段對應一個位的字節數(也就是說,總共 t_natts 位)。在這個位列裏面,爲 1 的位表示非空,而爲 0 的位表示空。如果沒有出現這個位圖,那麼所有數據字段都假設爲非空的。對象 ID 只有在設置了 t_infomask 裏面的 HEAP_HASOID 位的時候纔出現。如果出現,它正好出現在 t_hoff 範圍之前。如果需要補齊 t_hoff ,使之成爲 MAXALIGN 的倍數,那麼這些填充將出現在 null 位圖和對象 ID 之間。這樣也保證了對象 ID 得到恰當的對齊。
3.5特殊空間-Special space
說明:
1)最後一段是"特殊段",它可以包含任何訪問方法想存放的東西。比如,b-tree 索引存儲指向頁面的左右同宗的鏈接,以及其它一些和索引結構相關的數據。普通表並不使用這個段(通過設置 pd_special 等於頁面大小來表示)。