2. B樹索引的內部結構
我們可以使用如下方式將B樹索引轉儲成樹狀結構的形式而呈現出來:
我們可以使用如下方式將B樹索引轉儲成樹狀結構的形式而呈現出來:
alter session set events 'immediate trace name treedump level INDEX_OBJECT_ID';
比如,對於上面的例子來說,我們把創建在goodid上的名爲idx_warecountd_goodid的索引轉儲出來。
SQL> select object_id from user_objects where object_name='IDX_WARECOUNTD_GOODID';
OBJECT_ID
----------
89037
SQL> alter session set events 'immediate trace name treedump level 89037';
select value from v$diag_info where name='Default Trace File';
----- begin tree dump
branch: 0x1031b23 16980771 (0: nrow: 106, level: 2)
branch: 0x10556b0 17127088 (-1: nrow: 414, level: 1)
leaf: 0x1031b24 16980772 (-1: nrow: 363 rrow: 363)
leaf: 0x1031b25 16980773 (0: nrow: 359 rrow: 359)
leaf: 0x1031b26 16980774 (1: nrow: 359 rrow: 359)
leaf: 0x1031b27 16980775 (2: nrow: 359 rrow: 359)
leaf: 0x1031b28 16980776 (3: nrow: 359 rrow: 359)
leaf: 0x1031b29 16980777 (4: nrow: 359 rrow: 359)
leaf: 0x1031b2a 16980778 (5: nrow: 359 rrow: 359)
leaf: 0x1031b2b 16980779 (6: nrow: 359 rrow: 359)
leaf: 0x1031b2c 16980780 (7: nrow: 359 rrow: 359)
leaf: 0x1031b2d 16980781 (8: nrow: 359 rrow: 359)
leaf: 0x1031b2e 16980782 (9: nrow: 359 rrow: 359)
其中,每一行的第一列表示節點類型:branch表示分支節點(包括根節點),
而leaf則表示葉子節點;
第二列表示十六進制表示的節點的地址;
0x1031b23 十六進制 轉換爲10進制 16980771
第四列表示相對於前一個節點的位置,根節點從0開始計算
其他分支節點和葉子節點從-1開始計算
第五列的nrow表示當前節點中所含有的索引條目的數量。
上面這種方式以樹狀形式轉儲整個索引。同時,我們可以轉儲一個索引節點來看看其中存放了些什麼。轉儲的方式爲:
alter system dump datafile file# block block#;
我們從上面轉儲結果中的第二行知道,索引的根節點的地址爲16980771,因此我們先將其轉換爲文件號以及數據塊號。
select dbms_utility.data_block_address_file(16980771), dbms_utility.data_block_address_block(16980771) from dual;
SQL> select dbms_utility.data_block_address_file(16980771), dbms_utility.data_block_address_block(16980771) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16980771) DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16980771)
---------------------------------------------- -----------------------------------------------
4 203555
於是,我們轉儲根節點的內容。
SQL> alter system dump datafile 4 block 203555;
Branch block dump
=================
header address 140711254186060=0x7ff9e452584c
kdxcolev 2
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 105
kdxcofbo 238=0xee
kdxcofeo 6245=0x1865
kdxcoavs 6007
kdxbrlmc 17127088=0x10556b0
kdxbrsno 0
kdxbrbksz 8056
kdxbr2urrc 1
row#0[8039] dba: 17127509=0x1055855
col 0; len 8; (8): 35 30 32 39 30 20 20 20
col 1; len 3; (3): 01 03 3c
row#1[8022] dba: 17127931=0x10559fb
col 0; len 8; (8): 35 30 35 38 30 20 20 20
col 1; len 3; (3): 01 03 f0
row#2[8004] dba: 17128354=0x1055ba2
col 0; len 8; (8): 35 30 38 37 31 20 20 20
col 1; len 4; (4): 01 03 eb eb
row#3[7987] dba: 17128775=0x1055d47
col 0; len 8; (8): 35 31 31 36 31 20 20 20
col 1; len 3; (3): 01 04 a5
row#4[7970] dba: 17129196=0x1055eec
col 0; len 8; (8): 35 31 34 35 32 20 20 20
col 1; len 3; (3): 01 03 07
row#5[7952] dba: 17129620=0x1056094
col 0; len 8; (8): 35 31 37 34 32 20 20 20
col 1; len 4; (4): 01 03 89 46
row#6[7934] dba: 17130042=0x105623a
col 0; len 8; (8): 35 32 30 33 33 20 20 20
col 1; len 4; (4): 01 03 85 0e
row#7[7917] dba: 17130464=0x10563e0
col 0; len 8; (8): 35 32 33 32 34 20 20 20
col 1; len 3; (3): 01 03 80
row#8[7900] dba: 17130888=0x1056588
col 0; len 8; (8): 35 32 36 31 35 20 20 20
col 1; len 3; (3): 01 03 66
row#9[7883] dba: 17131310=0x105672e
row#103[6262] dba: 17170570=0x106008a
col 0; len 8; (8): 38 38 32 30 31 20 20 20
col 1; len 4; (4): 01 04 a1 b7
row#104[6245] dba: 17170718=0x106011e
col 0; len 8; (8): 38 38 35 30 34 20 20 20
col 1; len 3; (3): 01 03 04
----- end of branch block dump -----
kdxcolev 2:
其中的kdxcolev表示索引層級號,這裏由於我們轉儲的是根節點,所以其層級號爲2。
對葉子節點來說該值爲0;
kdxcolok 0:
kdxcolok表示該索引上是否正在發生修改塊結構的事務
kdxcosdc 0:
kdxcosdc表示索引結構發生變化的數量,當你修改表裏的某個索引鍵值時,該值增加
kdxconro 105:
kdxconro表示當前索引節點中索引條目的數量,但是注意,不包括kdxbrlmc指針
再往下可以看到如下的內容。這部分內容就是在根節點中所記錄的索引條目,總共是105個條目。再加上
kdxbrlmc所指向的第一個分支節點
每個索引條目都指向一個分支節點。其中col 1表示所鏈接的分支節點的地址,該值經過一定的轉換以後實際就是row#所在行的dba的值。
row#0[8039] dba: 17127509=0x1055855
col 0; len 8; (8): 35 30 32 39 30 20 20 20
col 1; len 3; (3): 01 03 3c
0x1055855 16進制,轉換爲10進制 17127509
col 0; len 8; (8): 35 30 32 39 30 20 20 20
從十六進制轉換爲十進制
35 30 32 39 30 20 20 20
53 48 50 57 48 32 32 32
to_number(NN,’XX’)的方式從十六進制轉換爲十進制
因爲我們已經知道索引鍵值是char類型的,所以對每個值都運用chr函數就可以得到被索引鍵值爲
53 48 50 57 48 32 32 32
5 0 2 9 0
SQL> select dump('50290') from dual
2 ;
DUMP('50290')
----------------------------
Typ=96 Len=5: 53,48,50,57,48
利用存儲過程轉換:
DECLARE
n VARCHAR2(2000);
BEGIN
DBMS_STATS.convert_raw_value('35', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('30', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('32', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('39', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('30', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('20', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('20', n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('20', n);
DBMS_OUTPUT.put_line(n);
END;
50290