PG12-2 B-Tree 索引 level 0 root頁
接上節,依然使用上節的用例
如下
postgres=# select * from bt_metap('pk_t_index'); magic | version | root | level | fastroot | fastlevel | oldest_xact | last_cleanup_num_tuples --------+---------+------+-------+----------+-----------+-------------+------------------------- 340322 | 4 | 1 | 0 | 1 | 0 | 0 | -1 (1 row) postgres=#
可以看到root page id = 1 。
postgres=# select * from bt_page_stats('pk_t_index',1); blkno | type | live_items | dead_items | avg_item_size | page_size | free_size | btpo_prev | btpo_next | btpo | btpo_flags -------+------+------------+------------+---------------+-----------+-----------+-----------+-----------+------+------------ 1 | l | 4 | 0 | 16 | 8192 | 8068 | 0 | 0 | 0 | 3 (1 row)
postgres=# select * from bt_page_items('pk_t_index',1); itemoffset | ctid | itemlen | nulls | vars | data ------------+-------+---------+-------+------+------------------------- 1 | (0,1) | 16 | f | f | 02 00 00 00 00 00 00 00 2 | (0,2) | 16 | f | f | 04 00 00 00 00 00 00 00 3 | (0,3) | 16 | f | f | 08 00 00 00 00 00 00 00 4 | (0,4) | 16 | f | f | 10 00 00 00 00 00 00 00 (4 rows) postgres=# select * from heap_page_items(get_raw_page('pk_t_index',1)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data ----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+-------- 1 | 8160 | 1 | 16 | | | | | | | | | | 2 | 8144 | 1 | 16 | | | | | | | | | | 3 | 8128 | 1 | 16 | | | | | | | | | | 4 | 8112 | 1 | 16 | | | | | | | | | | (4 rows) postgres=# postgres=# select * from page_header(get_raw_page('pk_t_index',1)); lsn | checksum | flags | lower | upper | special | pagesize | version | prune_xid -----------+----------+-------+-------+-------+---------+----------+---------+----------- 0/4D402D0 | 0 | 0 | 40 | 8112 | 8176 | 8192 | 4 | 0 (1 row)
根據root page id = 1檢視root page的stats
btpo=0 說明已經到了最底層
btpo_flags=3,說明它既是leaf又是root頁。
btpo_prev和btpo_next分別表示該頁的相鄰頁(branch page是雙向連結串列)。
btpo_flags 可以在程式碼中檢視(src/include/access/nbtree.h),一共有幾個
typedef struct BTPageOpaqueData { BlockNumber btpo_prev; /* left sibling, or P_NONE if leftmost */ BlockNumber btpo_next; /* right sibling, or P_NONE if rightmost */ union { uint32 level; /* tree level --- zero for leaf pages */ TransactionId xact; /* next transaction ID, if deleted */ } btpo; uint16 btpo_flags; /* flag bits, see below */ BTCycleId btpo_cycleid; /* vacuum cycle ID of latest split */ } BTPageOpaqueData; /* Bits defined in btpo_flags */ #define BTP_LEAF (1 << 0) /* leaf page, i.e. not internal page */ #define BTP_ROOT (1 << 1) /* root page (has no parent) */ #define BTP_DELETED (1 << 2) /* page has been deleted from tree */ #define BTP_META (1 << 3) /* meta-page */ #define BTP_HALF_DEAD (1 << 4) /* empty, but still in tree */ #define BTP_SPLIT_END (1 << 5) /* rightmost page of split group */ #define BTP_HAS_GARBAGE (1 << 6) /* page has LP_DEAD tuples */ #define BTP_INCOMPLETE_SPLIT (1 << 7) /* right sibling's downlink is missing */
BTPageOpaqueData儲存在page 1(這裡的page 1又是根節點,又是葉節點,還是子節點,所以不好說,是否每個節點頁都還包含這個資料結構,在下面的實驗中會體現)sepcial空間,如下
page1相對整個頁面的偏移為8192,而page 1的special空間相對頁頭偏移為8176,所以相對這個檔案偏移為16368
postgres@morro:~$ hexdump -C /var/lib/postgresql/data/pg12/base/12711/46918 -s 16368 -n 16 00003ff0 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 |................| 00004000 postgres@morro:~$
BTPageOpaqueData大小正好為16位元組,這裡不一一檢視每個域的值了,可以看到其他均為0,flags為3.
下面檢視一下,bt元組的items
先插入兩條新元組,先插入id為18,再插入id為17
postgres=# insert into t_index values(18,'4','d'); INSERT 0 1 postgres=# insert into t_index values(17,'4','d'); INSERT 0 1 postgres=# postgres=# select * from bt_page_items('pk_t_index',1); itemoffset | ctid | itemlen | nulls | vars | data ------------+-------+---------+-------+------+------------------------- 1 | (0,1) | 16 | f | f | 02 00 00 00 00 00 00 00 2 | (0,2) | 16 | f | f | 04 00 00 00 00 00 00 00 3 | (0,3) | 16 | f | f | 08 00 00 00 00 00 00 00 4 | (0,4) | 16 | f | f | 10 00 00 00 00 00 00 00 5 | (0,6) | 16 | f | f | 11 00 00 00 00 00 00 00 6 | (0,5) | 16 | f | f | 12 00 00 00 00 00 00 00 (6 rows) postgres=#
可以看到,實際資料儲存時是無序的(索性必須是有序的),但是索引的行指標是有序的
18對應的ctid為(0,5),17對應的ctid為(0,6),索引17存在18後面,所以是無序的,
但是(0,5)也就是18對應的行指標為lp6,(0,6)對應的行指標為lp5,所以行指標是有序的,正確的表示了索引值的大小。
透過這個例子,也就是說如果我們插入一個15的,15對應的ctid應該為(0,7)但是對應的行指標應該為lp4,10,17,18對應的行指標應該要後移一步。試一下
postgres=# select * from bt_page_items('pk_t_index',1); itemoffset | ctid | itemlen | nulls | vars | data ------------+-------+---------+-------+------+------------------------- 1 | (0,1) | 16 | f | f | 02 00 00 00 00 00 00 00 2 | (0,2) | 16 | f | f | 04 00 00 00 00 00 00 00 3 | (0,3) | 16 | f | f | 08 00 00 00 00 00 00 00 4 | (0,7) | 16 | f | f | 0f 00 00 00 00 00 00 00 5 | (0,4) | 16 | f | f | 10 00 00 00 00 00 00 00 6 | (0,6) | 16 | f | f | 11 00 00 00 00 00 00 00 7 | (0,5) | 16 | f | f | 12 00 00 00 00 00 00 00 (7 rows) postgres=#
結果和我們想的一樣。
我們再來解析一條item
bt元組的頭資訊如下,長度為8個位元組
typedef struct IndexTupleData { ItemPointerData t_tid; /* reference TID to heap tuple */ /* --------------- * t_info is laid out in the following fashion: * * //該元組是否為null * 15th (high) bit: has nulls * //該元組是否有可變長度的屬性 * 14th bit: has var-width attributes * //access method 定義其意義 * 13th bit: AM-defined meaning * //元組的大小 * 12-0 bit: size of tuple * --------------- */ unsigned short t_info; /* various info about tuple */ } IndexTupleData; typedef struct ItemPointerData { BlockIdData ip_blkid; //塊號 OffsetNumber ip_posid; //塊內偏移 } typedef struct BlockIdData { uint16 bi_hi; uint16 bi_lo; } BlockIdData;
檢視所有bt元組在頁內的偏移
postgres=# select * from heap_page_items(get_raw_page('pk_t_index',1)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid | t_data ----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+-------- 1 | 8160 | 1 | 16 | | | | | | | | | | 2 | 8144 | 1 | 16 | | | | | | | | | | 3 | 8128 | 1 | 16 | | | | | | | | | | 4 | 8064 | 1 | 16 | | | | | | | | | | 5 | 8112 | 1 | 16 | | | | | | | | | | 6 | 8080 | 1 | 16 | | | | | | | | | | 7 | 8096 | 1 | 16 | | | | | | | | | | (7 rows) postgres=#
以第一條元組為例,相對於檔案頭,該元組的偏移為8192+8160,長度為16位元組,其中8位元組為頭,
Tcid
postgres@morro:~$ hexdump -C /var/lib/postgresql/data/pg12/base/12711/46918 -s 16352 -n 4 00003fe0 00 00 00 00 |....| 00003fe4 postgres@morro:~$
對應(0, 1)中的0,注意這裡的t-cid指向的是堆表的元組位置,在本例中是t_index的page 0 的 1號元組。
postgres@morro:~$ hexdump -C /var/lib/postgresql/data/pg12/base/12711/46918 -s 16356 -n 2 00003fe4 01 00 |..| 00003fe6 postgres@morro:~$
1,對應(0,1)中的1.
t_Info
postgres@morro:~$ hexdump -C /var/lib/postgresql/data/pg12/base/12711/46918 -s 16358 -n 2 00003fe6 10 00 |..| 00003fe8 postgres@morro:~$
0X0010,根據上面的解釋,表示元組長度為16
元組的資訊為
postgres=# select * from bt_page_items('pk_t_index',1); itemoffset | ctid | itemlen | nulls | vars | data ------------+-------+---------+-------+------+------------------------- 1 | (0,1) | 16 | f | f | 02 00 00 00 00 00 00 00 2 | (0,2) | 16 | f | f | 04 00 00 00 00 00 00 00 3 | (0,3) | 16 | f | f | 08 00 00 00 00 00 00 00 4 | (0,7) | 16 | f | f | 0f 00 00 00 00 00 00 00 5 | (0,4) | 16 | f | f | 10 00 00 00 00 00 00 00 6 | (0,6) | 16 | f | f | 11 00 00 00 00 00 00 00 7 | (0,5) | 16 | f | f | 12 00 00 00 00 00 00 00 (7 rows) postgres=#
檢視第一條元組的資料
postgres@morro:~$ hexdump -C /var/lib/postgresql/data/pg12/base/12711/46918 -s 16360 -n 8 00003fe8 02 00 00 00 00 00 00 00 |........| 00003ff0 postgres@morro:~$
根據原始碼註釋如下
/* * Index tuple header structure * * All index tuples start with IndexTupleData. If the HasNulls bit is set, * this is followed by an IndexAttributeBitMapData. The index attribute * values follow, beginning at a MAXALIGN boundary. * * Note that the space allocated for the bitmap does not vary with the number * of attributes; that is because we don't have room to store the number of * attributes in the header. Given the MAXALIGN constraint there's no space * savings to be had anyway, for usual values of INDEX_MAX_KEYS. */ typedef struct IndexTupleData { ItemPointerData t_tid; /* reference TID to heap tuple */ /* --------------- * t_info is laid out in the following fashion: * * //該元組是否為null * 15th (high) bit: has nulls * //該元組是否有可變長度的屬性 * 14th bit: has var-width attributes * //access method 定義其意義 * 13th bit: AM-defined meaning * //元組的大小 * 12-0 bit: size of tuple * --------------- */ unsigned short t_info; /* various info about tuple */ } IndexTupleData; typedef struct IndexAttributeBitMapData { bits8 bits[(INDEX_MAX_KEYS + 8 - 1) / 8]; } IndexAttributeBitMapData;
所以如果元組為null,才會跟上 IndexAttributeBitMapData
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70012752/viewspace-2886383/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PG 12-2 B-Tree 索引 分析 分裂 level = 1索引
- B-tree索引索引
- PostgreSQL的B-tree索引SQL索引
- MySQL探索(一):B-Tree索引MySql索引
- PostgreSQL Page頁結構解析(5)- B-Tree索引儲存結構#1SQL索引
- PostgreSQL Page頁結構解析(6)- B-Tree索引儲存結構#2SQL索引
- PostgreSQL Page頁結構解析(7)- B-Tree索引儲存結構#3SQL索引
- BUU_jarvisoj_level0JAR
- natas(level0-level14)通關詳細指南(一)
- 64_索引管理_mapping root object深入剖析索引APPObject
- B-tree
- 啟動Jmeter5.3 後彈出警告: WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0JMeterJava
- PWN(棧溢位漏洞)-原創小白超詳細[Jarvis-level0]JAR
- 十四、Mysql之B-TreeMySql
- Level Up
- MySQL 配置索引頁的合併閾值MySql索引
- 記一次kafka的high level和low levelKafka
- 《從0開始學Elasticsearch》—叢集健康和索引管理Elasticsearch索引
- E. Level Up
- E - Level K Palindrome
- CSS LEVEL4CSS
- 【MySQL(1)| B-tree和B+tree】MySql
- 解決root使用者不能開啟Chromium網頁瀏覽器網頁瀏覽器
- Maximize the Root
- RuneScape - To verify your level of combatBAT
- [LintCode] Binary Tree Level Order
- FUNBOX-5: NEXT LEVEL
- 多路查詢樹:B-tree/b+tree
- 淺析oracle b-tree index搜尋原理OracleIndex
- 【ElasticSearch】ElasticSearch 7.x 預設不在支援指定索引型別 Failed to parse mapping [_doc]: Root mapping definitioElasticsearch索引型別AIAPP
- Change Buffer 只適用於非唯一索引頁?錯索引
- GRANT ALL PRIVILEGES ON *.* TO ‘root‘@‘%‘ IDENTIFIED BY ‘root‘ WITH GRANT OPTION;報錯IDE
- 取消 root 級管理員的 root 許可權
- 2.3.1.2 Application RootAPP
- CSS E:rootCSS
- Root of AVL Tree
- SCSS @at-rootCSS
- 電平(level)&脈衝(pulse)