天天看點

Oracle索引内部結構研究

1. 建立一個塊大小為2KB的表空間

create tablespace tbs_2k datafile 'C:\APP\ADMINISTRATOR\ORADATA\HXL11G\hxl01.DBF' size 128m blocksize 2k;
           

如果報錯執行如下語句:

alter system set db_2k_cache_size=50 scope=both;
           

2. 建立測試表

drop table index_test;

create table index_test(id char(150)) tablespace tbs_2k;

create index idx_test on index_test(id) tablespace tbs_2k;
           

3. 檢視空索引内部結構

select object_id from user_objects where object_name='IDX_TEST';

alter session set events 'immediate trace name treedump level 69907';--69907為上一個SQL查出來的結果
           

4. 在oracle日志記錄的地方一般是在udump檔案夾下面,找到一個修改時間最新的檔案。我機器的檔案是 orcl_ora_5576.trc,如下所示

Oracle索引内部結構研究
Oracle索引内部結構研究

5. 打開這個日志檔案我們可以看到如下内容

----- begin tree dump

leaf: 0x48000c5 75497669 (0: nrow: 0 rrow: 0)

----- end tree dump

left代表葉子節點,0: nrow: 0 rrow: 0:0代表層級,nrow表示目前節點中所含有的索引條目的數量,rrow表示有效的索引條目。nrow-rrow表示删除的索引條目(無效條目)

6. 往表裡面插入10行資料,同時檢視索引結構

begin
for i in 1..10 loop
insert into index_test values (rpad(to_char(i*2),150,'a'));
end loop;
end;
/

commit;

alter session set events 'immediate trace name treedump level 69907';
           

打開最新的那個日志檔案,可以看到如下内容

----- begin tree dump

leaf: 0x48000c5 75497669 (0: nrow: 10 rrow: 10)

----- end tree dump

nrow和rrow都變成了10,意思是這一個塊存放了10個有效的索引條目

7. 檢視索引塊的内部結構

select dbms_utility.data_block_address_file(75497669),
dbms_utility.data_block_address_block(75497669) from dual;--75497669為索引塊位址

alter system dump datafile 18 block 197;--18,197為上一步查詢的結果
           

打開最新日志檔案我們會看到如下内容

Leaf block dump

===============

header address 135955556=0x81a8464

kdxcolev 0 --索引層級号

KDXCOLEV Flags = - - -

kdxcolok 0 --該索引上是否正在發生修改塊結構的事務

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y  --内部操作代碼

kdxconco 2 --索引條目中列的數量

kdxcosdc 0 --索引結構發生變化的數量,當你修改表裡的某個索引鍵值時,該值增加

kdxconro 10 --表示目前索引節點中索引條目的數量

kdxcofbo 56=0x38 --目前索引節點中可用空間的起始點相對目前塊的位移量

kdxcofeo 282=0x11a --目前索引節點中可用空間的最尾端的相對目前塊的位移量

kdxcoavs 226 --目前索引塊中的可用空間總量,也就是用kdxcofeo減去kdxcofbo得到的

kdxlespl 0 --當葉子節點被拆分時未送出的事務數量

kdxlende 0 --表示被删除的索引條目的數量

kdxlenxt 0=0x0 --表示目前葉子節點的下一個葉子節點的位址

kdxleprv 0=0x0 --表示目前葉子節點的上一個葉子節點的位址

kdxledsz 0 --表示可用空間

kdxlebksz 1892 --可用資料塊的空間大小,2KB應該是2048,應該是預留了一些空間

row#0[1087] flag: ------, lock: 2, len=161  --其中flag表示标記,比如删除标記等;而lock表示鎖定資訊,len表示長度

col 0; len 150; (150):  --col 0表示索引鍵值

 31 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

col 1; len 6; (6):  04 80 00 af 00 04 --col 1表示ROWID

8.繼續插入一行,檢視kdxcoavs(可用空間)

insert into index_test values(rpad(to_char(11*2),150,'a'));

alter system dump datafile 18 block 197;
           

日志片段如下

Leaf block dump

===============

header address 135955556=0x81a8464

kdxcolev 0

KDXCOLEV Flags = - - -

kdxcolok 0

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 2

kdxcosdc 0

kdxconro 11

kdxcofbo 58=0x3a

kdxcofeo 121=0x79

kdxcoavs 63 --可用空間由226程式設計了63,一個索引條目226-63=163

kdxlespl 0

kdxlende 0

kdxlenxt 0=0x0

kdxleprv 0=0x0

kdxledsz 0

kdxlebksz 1892

9. 繼續插入一行,這個時候索引塊空間不夠,會産生裂變。這個索引塊變成了根節點,下面又挂了兩個子節點,然後将索引條目進行拆分,一邊放一點

insert into index_test values(rpad(to_char(12*2),150,'a'));

alter system dump datafile 18 block 197;
           

檢視日志片段:

Branch block dump

=================

header address 135955532=0x81a844c

kdxcolev 1

KDXCOLEV Flags = - - -

kdxcolok 1

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 2

kdxcosdc 1

kdxconro 1

kdxcofbo 30=0x1e

kdxcofeo 1909=0x775

kdxcoavs 1879

kdxbrlmc 75497687=0x48000d7 --第一個葉子節點位置

kdxbrsno 0

kdxbrbksz 1916 

kdxbr2urrc 0

row#0[1909] dba: 75497670=0x48000c6 --第二個葉子節點位置

col 0; len 1; (1):  34

col 1; TERM

10. 檢視第一個葉子塊内部結構

select dbms_utility.data_block_address_file(75497687),
dbms_utility.data_block_address_block(75497687) from dual; --75497687第一個葉子塊位址

alter system dump datafile 18 block 215; --上一步查詢結果
           

日志片段如下:

Leaf block dump

===============

header address 135955556=0x81a8464

kdxcolev 0 --0層

KDXCOLEV Flags = - - -

kdxcolok 0

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 2 --兩列

kdxcosdc 1

kdxconro 9 --9行索引條目,說明插入12行索引條目的時候裂變成2個葉子塊,該葉子塊存放9個索引條目,另一個葉子塊存放3個索引條目

kdxcofbo 54=0x36

kdxcofeo 282=0x11a

kdxcoavs 389

kdxlespl 0

kdxlende 0

kdxlenxt 75497670=0x48000c6 --下一個葉子塊位址

kdxleprv 0=0x0

kdxledsz 0

kdxlebksz 1892

row#0[443] flag: ----S-, lock: 2, len=161

col 0; len 150; (150): 

 31 30 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

col 1; len 6; (6):  04 80 00 af 00 04

11. 檢視第二個葉子塊内部結構

select dbms_utility.data_block_address_file(75497670),
dbms_utility.data_block_address_block(75497670) from dual;--75497670為葉子塊位址

alter system dump datafile 18 block 198;--18,198上一步查詢結果
           

檢視日志片段

Leaf block dump

===============

header address 135955556=0x81a8464

kdxcolev 0

KDXCOLEV Flags = - - -

kdxcolok 1

kdxcoopc 0x87: opcode=7: iot flags=--- is converted=Y

kdxconco 2

kdxcosdc 1

kdxconro 3 --驗證了上一步,這裡面存放了3個索引條目

kdxcofbo 42=0x2a

kdxcofeo 1409=0x581

kdxcoavs 1367

kdxlespl 0

kdxlende 0

kdxlenxt 0=0x0

kdxleprv 75497687=0x48000d7 --上一個索引塊位址

kdxledsz 0

kdxlebksz 1892

row#0[1409] flag: ----S-, lock: 2, len=161

col 0; len 150; (150): 

 34 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

col 1; len 6; (6):  04 80 00 af 00 01