#####內部結構session
將B樹索引轉儲成樹狀結構的形式而呈現出來:oracle
alter session set events 'immediate trace name treedump level INDEX_OBJECT_ID';
app
SQL> alter session set events 'immediate trace name treedump level 126545'; Session altered. [oracle@hzvscmdb trace]$ pwd /home/oracle/app/oracle/diag/rdbms/tonytest/tonytest/trace [oracle@hzvscmdb trace]$ vi tonytest_ora_5439.trc ----- begin tree dump branch: 0x34000e3 54526179 (0: nrow: 444, level: 1) leaf: 0x34000e4 54526180 (-1: nrow: 393 rrow: 393) leaf: 0x34000e5 54526181 (0: nrow: 377 rrow: 377) leaf: 0x34000e6 54526182 (1: nrow: 378 rrow: 378) leaf: 0x34000e7 54526183 (2: nrow: 377 rrow: 377) leaf: 0x34000e8 54526184 (3: nrow: 377 rrow: 377) leaf: 0x34000e9 54526185 (4: nrow: 378 rrow: 378) leaf: 0x34000ea 54526186 (5: nrow: 379 rrow: 379) leaf: 0x34000eb 54526187 (6: nrow: 379 rrow: 379) leaf: 0x34000ec 54526188 (7: nrow: 379 rrow: 379) ………………… ----- end tree dump
- 每一行的第一列表示節點類型>:branch表示分支節點(包括根節點),而leaf則表示葉子節點;
- 第二列表示十六進制表示的節點的地址;
- 第三列表示十進制表示的節點的地址;
- 第四列表示相對於前一個節點的位置,根節點從0開始計算,其餘分支節點和葉子節點從-1開始計算;
- 第五列的nrow表示當前節點中所含有的索引條目的數量。好比咱們能夠看到根節點中含有的nrow爲444,表示根節點中含有444個索引條目,分別指向444個分支節點;
- 第六列中的rrow表示有效的索引條目(由於索引條目若是被刪除,不會當即被清除出索引塊中。因此nrow減rrow的數量就表示已經被刪除的索引條目數量)的數量,好比對於第一個leaf來講,其rrow爲393,也就是說該葉子節點中存放了393個可用索引條目,分別指向表emp3的393條記錄。
轉儲一個索引節點oop
alter system dump datafile file# block block#;
指針
select dbms_utility.data_block_address_file(54526179), dbms_utility.data_block_address_block(54526179) from dual; DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(54526179) DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(54526179) ---------------------------------------------- ----------------------------------------------- 13 227 SQL> alter system dump datafile 13 block 227; System altered. Branch block dump ================= header address 140301252250188=0x7f9a6e4d4a4c kdxcolev 1 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 2 kdxcosdc 0 kdxconro 443 kdxcofbo 914=0x392 kdxcofeo 2739=0xab3 kdxcoavs 1825 kdxbrlmc 54526180=0x34000e4 kdxbrsno 49 kdxbrbksz 8056 kdxbr2urrc 3
- kdxcolev表示索引層級號,這裏因爲咱們轉儲的是根節點,因此其層級號爲1。對葉子節點來講該值爲0;
- kdxcolok表示該索引上是否正在發生修改塊結構的事務;
- kdxcoopc表示內部操做代碼;
- kdxconco表示索引條目中列的數量;
- kdxcosdc表示索引結構發生變化的數量,當你修改表裏的某個索引鍵值時,該值增長;
- kdxconro表示當前索引節點中索引條目的數量,可是注意,不包括kdxbrlmc指針;
- kdxcofbo表示當前索引節點中可用空間的起始點相對當前塊的位移量;
- kdxcofeo表示當前索引節點中可用空間的最尾端的相對當前塊的位移量;
- kdxcoavs表示當前索引塊中的可用空間總量,也就是用kdxcofeo減去kdxcofbo獲得的。
- kdxbrlmc表示分支節點的地址,
- kdxbrsno表示最後一個被修改的索引條目號,若是=0,表示該索引是新建的索引;
- kdxbrbksz表示可用數據塊的空間大小。實際從這裏已經能夠看到,即使是PCTFREE設置爲0,也不能用足8192字節。
row#0[8043] dba: 54526181=0x34000e5 col 0; len 7; (7): 64 65 76 32 32 34 39 col 1; TERM row#1[8030] dba: 54526182=0x34000e6 col 0; len 7; (7): 64 65 76 32 36 32 36 col 1; TERM row#2[8017] dba: 54526183=0x34000e7 col 0; len 7; (7): 64 65 76 33 30 30 33 col 1; TERM row#3[8005] dba: 54526184=0x34000e8 col 0; len 6; (6): 64 65 76 33 33 38 col 1; TERM
每一個索引條目都指向一個分支節點。 col 1表示所連接的分支節點的地址,該值通過必定的轉換之後實際就是row#所在行的dba的值。若是根節點下沒有其餘的分支節點,則col 1爲TERM; col 0表示該分支節點所連接的最小鍵值。code
#索引高度爲1 ----- begin tree dump *** 2015-07-10 07:05:03.971 branch: 0x34000e3 54526179 (0: nrow: 479, level: 1) leaf: 0x34000e4 54526180 (-1: nrow: 272 rrow: 272) leaf: 0x34004c9 54527177 (0: nrow: 272 rrow: 272) leaf: 0x34004d3 54527187 (1: nrow: 272 rrow: 272) leaf: 0x34004ab 54527147 (2: nrow: 272 rrow: 272) leaf: 0x34004af 54527151 (3: nrow: 272 rrow: 272) ......... leaf: 0x34004a9 54527145 (473: nrow: 420 rrow: 420) leaf: 0x34004ad 54527149 (474: nrow: 420 rrow: 420) leaf: 0x34004b1 54527153 (475: nrow: 420 rrow: 420) leaf: 0x34004b5 54527157 (476: nrow: 420 rrow: 420) leaf: 0x34004e2 54527202 (477: nrow: 96 rrow: 96) ----- end tree dump #模擬插入數據,而後根節點分裂,索引高度爲2 SQL> alter session set events 'immediate trace name treedump level 126545'; Session altered. ----- begin tree dump branch: 0x34000e3 54526179 (0: nrow: 3, level: 2) branch: 0x34005d7 54527447 (-1: nrow: 253, level: 1) leaf: 0x34000e4 54526180 (-1: nrow: 272 rrow: 272) leaf: 0x34005e1 54527457 (0: nrow: 272 rrow: 272) leaf: 0x34005f1 54527473 (1: nrow: 272 rrow: 272) leaf: 0x34005fa 54527482 (2: nrow: 272 rrow: 272) leaf: 0x34005fe 54527486 (3: nrow: 272 rrow: 272) ......... leaf: 0x3400779 54527865 (246: nrow: 272 rrow: 272) leaf: 0x3400766 54527846 (247: nrow: 272 rrow: 272) leaf: 0x340076a 54527850 (248: nrow: 310 rrow: 310) leaf: 0x340076d 54527853 (249: nrow: 379 rrow: 379) leaf: 0x34005b9 54527417 (250: nrow: 271 rrow: 271) leaf: 0x34005bd 54527421 (251: nrow: 272 rrow: 272) branch: 0x34007e2 54527970 (0: nrow: 256, level: 1) leaf: 0x34005a7 54527399 (-1: nrow: 272 rrow: 272) leaf: 0x34005a8 54527400 (0: nrow: 265 rrow: 265) leaf: 0x34005ac 54527404 (1: nrow: 272 rrow: 272) leaf: 0x3400597 54527383 (2: nrow: 471 rrow: 471) leaf: 0x3400582 54527362 (3: nrow: 271 rrow: 271) leaf: 0x3400586 54527366 (4: nrow: 267 rrow: 267) ......... leaf: 0x3400273 54526579 (249: nrow: 212 rrow: 212) leaf: 0x340022c 54526508 (250: nrow: 212 rrow: 212) leaf: 0x3400230 54526512 (251: nrow: 212 rrow: 212) leaf: 0x3400277 54526583 (252: nrow: 212 rrow: 212) leaf: 0x340027b 54526587 (253: nrow: 213 rrow: 213) leaf: 0x340027f 54526591 (254: nrow: 393 rrow: 393) branch: 0x34005da 54527450 (1: nrow: 278, level: 1) leaf: 0x34000ff 54526207 (-1: nrow: 213 rrow: 213) leaf: 0x3400246 54526534 (0: nrow: 212 rrow: 212) leaf: 0x3400240 54526528 (1: nrow: 212 rrow: 212) leaf: 0x3400244 54526532 (2: nrow: 212 rrow: 212) leaf: 0x3400266 54526566 (3: nrow: 212 rrow: 212) leaf: 0x340026a 54526570 (4: nrow: 212 rrow: 212) ......... leaf: 0x34004a5 54527141 (271: nrow: 420 rrow: 420) leaf: 0x34004a9 54527145 (272: nrow: 420 rrow: 420) leaf: 0x34004ad 54527149 (273: nrow: 420 rrow: 420) leaf: 0x34004b1 54527153 (274: nrow: 420 rrow: 420) leaf: 0x34004b5 54527157 (275: nrow: 420 rrow: 420) leaf: 0x34004e2 54527202 (276: nrow: 96 rrow: 96) ----- end tree dump Branch block dump ================= header address 140408996839500=0x7fb38461404c kdxcolev 2 KDXCOLEV Flags = - - - kdxcolok 0 kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y kdxconco 2 kdxcosdc 1 kdxconro 2 kdxcofbo 32=0x20 kdxcofeo 8030=0x1f5e kdxcoavs 7998 kdxbrlmc 54527447=0x34005d7 kdxbrsno 0 kdxbrbksz 8056 kdxbr2urrc 3 row#0[8030] dba: 54527970=0x34007e2 col 0; len 3; (3): 64 65 76 col 1; len 6; (6): 03 40 06 dc 00 92 row#1[8045] dba: 54527450=0x34005da col 0; len 5; (5): 71 61 33 33 39 col 1; TERM ----- end of branch block dump ----- End dump data blocks tsn: 19 file#: 13 minblk 227 maxblk 227
#####索引訪問索引
當oracle須要訪問索引裏的某個索引條目時,oracle是如何找到該索引條目所在的數據塊的呢?進程
當oracle進程須要訪問數據文件裏的數據塊時,oracle會有兩種類型的I/O操做方式:事件
- 隨機訪問,每次讀取一個數據塊(經過等待事件「db file sequential read」體現出來)。
- 順序訪問,每次讀取多個數據塊(經過等待事件「db file scattered read」體現出來)。
第一種方式則是訪問索引裏的數據塊,而第二種方式的I/O操做屬於全表掃描。這裏順帶有一個問題,爲什麼隨機訪問會對應到db file sequential read等待事件,而順序訪問則會對應到db file scattered read等待事件呢?這彷佛反過來了,隨機訪問才應該是分散(scattered)的,而順序訪問才應該是順序(sequential)的。其實,等待事件主要根據實際獲取物理I/O塊的方式來命名的,而不是根據其在I/O子系統的邏輯方式來命名的。下面對於如何獲取索引數據塊的方式中會對此進行說明。事務
咱們看到前面對B樹索引的體系結構的描述,能夠知道其爲一個樹狀的立體結構。其對應到數據文件裏的
排列固然仍是一個平面的形式,也就是像下面這樣。所以,當oracle須要訪問某個索引塊的時候,勢必會在這個結構上跳躍的移動。
/根/分支/分支/葉子/…/葉子/分支/葉子/葉子/…/葉子/分支/葉子/葉子/…/葉子/分支/.....
當oracle須要得到一個索引塊時,首先從根節點開始,根據所要查找的鍵值,從而知道其所在的下一層的分支節點,而後訪問下一層的分支節點,再次一樣根據鍵值訪問再下一層的分支節點,如此這般,最終訪問到最底層的葉子節點。能夠看出,其得到物理I/O塊時,是一個接着一個,按照順序,串行進行的。在得到最終物理塊的過程當中,咱們不能同時讀取多個塊,由於咱們在沒有得到當前塊的時候是不知道接下來應該訪問哪一個塊的。所以,在索引上訪問數據塊時,會對應到db file sequential read等待事件,其根源在於咱們是按照順序從一個索引塊跳到另外一個索引塊,從而找到最終的索引塊的。
那麼對於全表掃描來講,則不存在訪問下一個塊以前須要先訪問上一個塊的狀況。全表掃描時,oracle知道要訪問全部的數據塊,所以惟一的問題就是儘量高效的訪問這些數據塊。所以,這時oracle能夠採用同步的方式,分幾批,同時獲取多個數據塊。這幾批的數據塊在物理上多是分散在表裏的,所以其對應到db file scattered read等待事件。