<!--[if !supportLists]-->1) <!--[endif]-->叶子节点(Leaf node):包含条目直接指向表里的数据行。
<!--[if !supportLists]-->2) <!--[endif]-->分支节点(Branch node):包含的条目指向索引里其他的分支节点或者是叶子节点。
<!--[if !supportLists]-->3) <!--[endif]-->根节点(Root node):一个B树索引只有一个根节点,它实际就是位于树的最顶端的分支节点。
-------------- ----------
88217 88217
找到索引对应的OBJECT_ID,我们再用treedump来dump对应的OBJECT。
------------------------------------ ----------- ------------------------------
user_dump_dest string /oracle/admin/orcl/udump
----- begin tree dump
branch: 0x140110c 20975884 (0: nrow: 51, level: 1)
leaf: 0x140110d 20975885 (-1: nrow: 372 rrow: 372)
leaf: 0x140110e 20975886 (0: nrow: 336 rrow: 336)
leaf: 0x140110f 20975887 (1: nrow: 340 rrow: 340)
leaf: 0x1401110 20975888 (2: nrow: 336 rrow: 336)
leaf: 0x1401111 20975889 (3: nrow: 338 rrow: 338)
leaf: 0x1401112 20975890 (4: nrow: 338 rrow: 338)
leaf: 0x1401142 20975938 (49: nrow: 29 rrow: 29)
----- end tree dump
结构说明:
leaf:表示该数据块是leaf block
0x140110d:对应索引数据块的十六进位地址
20975885:对应索引数据块的十进位地址
-1: 表示索引数据块的编号,编号起始是-1
nrow: 372 :表示该索引数据块中总的行数,包含被删除的行
rrow: 372:表示该索引数据块中实际存在有效行数
####################################################################
通过视图查询索引的详细信息如下:
------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- ----------- ----------
INDEX_ORAGNISE 72 2 17290 51 50 1 415824 360985
2 dbms_utility.data_block_address_block(20975884) "block"
3 from dual;
---------- ----------
5 4364
2 dbms_utility.data_block_address_block(20975886) "block"
3 from dual;
---------- ----------
5 4366
=================
header address 381738060=0x16c0dc4c
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: pcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 50
kdxcofbo 128=0x80
kdxcofeo 7364=0x1cc4
kdxcoavs 7236
kdxbrlmc 20975885=0x140110d
kdxbrsno 0
kdxbrbksz 8056
kdxbr2urrc 3
row#0[8040] dba: 20975886=0x140110e
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 34
row#1[8027] dba: 20975887= 0x140110f
col 0; len 7; (7): 31 33 30 34 33 32 30
col 1; TERM
row#2[8014] dba: 20975888=0x1401110
col 0; len 7; (7): 31 33 30 39 30 30 31
col 1; TERM
row#3[8004] dba: 20975889=0x1401111
col 0; len 4; (4): 31 34 30 33
col 1; TERM
row#4[7988] dba: 20975890=0x1401112
col 0; len 10; (10): 31 34 32 34 30 30 30 32 30 32
col 1; TERM
对于分支节点块(包括根节点块)来说,其所包含的索引条目都是按照顺序排列的(缺省是升序排列,也可以在创建索引时指定为降序排列)。每个索引条目(也可以叫做每条记录)都具有两个字段。第一个字段表示当前该分支节点块下面所链接的索引块中所包含的最小键值;第二个字段为四个字节,表示所链接的索引块的地址,该地址指向下面一个索引块。在一个分支节点块中所能容纳的记录行数由数据块大小以及索引键值的长度决定。比如从上可以看到,对于根节点块来说,包含五条记录,它们指向五个分支节点块。其中col 0对应的数值分别表示分支节点块所链接的键值的最小值。而如dba:dba: 20975887=0x140110f则表示所指向的五个分支节点块的地址,包括十进制与十六进制地址。而col 1没看出有什么用,还希望有高手指点。
根据以上内容中,branch 20975886 得到更详细内容
2 dbms_utility.data_block_address_block(20975886) "block"
3 from dual;
---------- ----------
5 4366
===============
header address 381738084=0x16c0dc64
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: pcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 336
kdxcofbo 708=0x2c4
kdxcofeo 1530=0x5fa
kdxcoavs 822
kdxlespl 0
kdxlende 0
kdxlenxt 20975887= 0x140110f -- 下个节点RBA地址
kdxleprv 20975885=0x140110d -- 上一个节点RBA地址
kdxledsz 0
kdxlebksz 8032
row#0[8012] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 34
col 1; len 6; (6): 01 40 10 70 00 48
row#1[7992] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 35
col 1; len 6; (6): 01 40 10 4d 00 19
row#2[7972] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 36
col 1; len 6; (6): 01 40 11 08 00 0f
row#3[7952] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 37
col 1; len 6; (6): 01 40 10 4d 00 26
row#4[7932] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 38
col 1; len 6; (6): 01 40 10 6c 00 39
row#5[7912] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 39
col 1; len 6; (6): 01 40 10 4d 00 27
row#6[7892] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 32 30
col 1; len 6; (6): 01 40 10 80 00 16
结构说明:
header address 381738084=0x16c0dc64
kdxcolev 0 (index level, 0表示是leaf block)
KDXCOLEV Flags = - - -
kdxcolok 0
kdxconco 2 索引列数量
kdxcosdc 0 索引结构改变次数
kdxconro 336 索引记录数量BR_ROWS
kdxcofbo 708=0x2c4 空闲空间开始偏移量
kdxcofeo 1530=0x5fa 空闲空间结束偏移量
kdxcoavs 822 所提供的空闲空间
kdxlespl 0 在数据块被cleaned out时,还未进行commit的数量
kdxlende 0 被删除索引记录的数量
kdxlenxt 20975887=0x140110f 下一个链接数据块的地址
kdxleprv 20975885=0x140110d 上一个链接数据块地址
kdxledsz 0 被删除的空间大小
kdxlebksz 8032 使用的数据块空间
kdxcolev: index level (0 represents leaf blocks)
kdxcolok: denotes whether structural block transaction is occurring
kdxcoopc: internal operation code
kdxconco: index column count
kdxcosdc: count of index structural changes involving block
kdxconro: number of index entries (does not include kdxbrlmc pointer)
kdxcofbo: offset to beginning of free space within block
kdxcofeo: offset to the end of free space (ie. first portion of block containing index data)
kdxcoavs: available space in block (effectively area between the two fields above)
row#0[8012] flag: ------, lock: 0, len=20
col 0; len 10; (10): 31 33 30 31 30 34 30 30 31 34
col 1; len 6; (6): 01 40 10 70 00 48
col 1: 为Rowid
关于rowid的换算:
(关于rowid解读,参考:我的ROWID解读)
关于整数key值的换算:
先去掉c2,因为c2只表示最高位的位置,后面才是真正数据,06转换为十进制为6,减去1为5,3b转换为十进制为48+11=59,
减去1为 58,两个结果合并到一起,为258,这就是其存储的真正数据,简单表示一下:
1. c2 03 3b -> 03 3b
2. 03 -> 0*16+3=3->3-1=2
3. 3b -> 3*16+14=59 -> 59-1=58
4. 结果合并得到258
关于字符串的换算:直接由十六进制得到各个ascii码,然后对应到相应字符。
这个换算没有得到验证???????
这种dump信息要参考DSI
注意:上面红色的字体标识该索引块的键值中最小的键值,也就是下面第一个索引叶节点块的第一个索引项对应的数值。
###########################################################################
假设我们有一个非分区表,表名为warecountd,其数据行数为130万行。该表中有一个列,列名为goodid,其类型为char(8),那么也就是说该goodid的长度为固定值:8。同时在该列上创建了一个B树索引。
在叶子节点中,每个索引条目都会在数据块中占一行空间。每一行用2到3个字节作为行头,行头用来存放标记以及锁定类型等信息。同时,在第一个表示索引的键值的字段中,每一个索引列都有1个字节表示数据长度,后面则是该列具体的值。那么对于本例来说,在叶子节点中的一行所包含的数据大致如下图二所示:
![bb](http://img.blog.itpub.net/blog/attachments/2008/05/9842_200805271324061.jpg?x-oss-process=style/bb)
从上图可以看到,在本例的叶子节点中,一个索引条目占18个字节。同时我们知道8KB的数据块中真正可以用来存放索引条目的空间为6488字节,那么在本例中,一个数据块中大约可以放360(6488/18)个索引条目。而对于我们表中的130万条记录来说,则需要大约3611(1300000/360)个叶子节点块。
而对于分支节点里的一个条目(一行)来说,由于它只需保存所链接的其他索引块的地址即可,而不需要保存具体的数据行在哪里,因此它所占用的空间要比叶子节点要少。分支节点的一行中所存放的所链接的最小键值所需空间与上面所描述的叶子节点相同;而存放的索引块的地址只需要4个字节,比叶子节点中所存放的ROWID少了2个字节,少的这2个字节也就是ROWID中用来描述在数据块中的行号所需的空间。因此,本例中在分支节点中的一行所包含的数据大致如下图三所示:
![bb](http://img.blog.itpub.net/blog/attachments/2008/05/9842_200805271324231.jpg?x-oss-process=style/bb)
从上图可以看到,在本例的分支节点中,一个索引条目占16个字节。根据上面叶子节点相同的方式,我们可以知道一个分支索引块可以存放大约405(6488/16)个索引条目。而对于我们所需要的3611个叶子节点来说,则总共需要大约9个分支索引块。
这样,我们就知道了我们的这个索引有2层,第一层为1个根节点,第二层为9个分支节点,而叶子节点数为3611个,所指向的表的行数为1300000行。但是要注意,在oracle的索引中,层级号是倒过来的,也就是说假设某个索引有N层,则根节点的层级号为N,而根节点下一层的分支节点的层级号为N-1,依此类推。对本例来说,9个分支节点所在的层级号为1,而根节点所在的层级号为2。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/9399028/viewspace-682646/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/9399028/viewspace-682646/