一. B-Tree Index原理
官网说明:
No index structure can satisfy all needs, butthe self-balancing B-tree index comes closest to optimizing the performance of searches on large sets of data.Each B-tree node holds multiple keys and pointers. The maximum number of keys in a node supported by a specific B-tree is the order of that tree.Each node has a potential of order+1 pointers to the level below it.
For example, the order=2 B-tree illustrated inFigure 7-1has tree pointers: to child nodes whose value is less than the first key, to the child nodes whose value is greater than the first key and less than the second key, and to the child nodes whose value is greater than the second key. Thus,the B-tree algorithm minimizes the number of reads and writes necessary to locate a record by passing through fewer nodes than in a binary tree algorithm, which has only one key and at most two children for each decision node.Here we describe theKnuth variationin which the index consists of two parts: a sequence set that provides fast sequential access to the data, and an index set that provides direct access to the sequence set.
Although the nodes of a B-tree generally do not contain the same number of data values, and they usually contain a certain amount of unused space,the B-tree algorithm ensures that the tree remains balanced and that the leaf nodes are at the same level.
Oracle中的Btree Index具有3大结构,root节点,branch节点,leaf节点. Root节点始终紧跟索引段头.当索引比较小的时候,root节点,branch节点,leaf节点都存储在同一个block中.
Branch节点主要存储了索引的键值,但是这个键值并不是完整的,它只是完整索引值的部分前缀.同时Branch节点还存储了指向leaf节点的指针(DBA),另外有个主意的是branch节点中还有个叫kdxbrlmc的指针.
Oracle rdba和dba说明
http://blog.youkuaiyun.com/xujinyang/article/details/6829256
Leaf节点主要存储了完整的索引键值,以及相关索引键值的部分rowid(这个rowid去掉了data object number部分),同时leaf节点还存储了2个指针(DBA),他们分别指向上一个leaf节点以及下一个leaf节点.
Btree Index是始终平衡的,也就是说从Root节点到Leaf节点的任何一个路径都是等距离的.
Btree Index默认是按照索引值升序排列的,当然了我们可以在创建/重建的时候设置它降序排列.
Index Scan的时候,采用的是sequential read,并且一次只能读一个block(INDEX FAST FULL SCAN除外).
Btree Index Update的时候,先做的是delete,然后进行insert.
Btree Index不存储Null值,但是如果组合索引其中一列是非Null的,那么组合索引也会存储Null值.
二. Tree Index存储原理
2.1创建测试数据
SYS@anqing2(rac2)> select * from v$version where rownum=1;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
SYS@anqing2(rac2)> create table te as select * fromdba_objects;
Table created.
SYS@anqing2(rac2)> select count(*) from te;
COUNT(*)
----------
50258
SYS@anqing2(rac2)> insert into te select * from dba_objects;
50258 rows created.
SYS@anqing2(rac2)> commit;
Commit complete.
SYS@anqing2(rac2)> select count(*) from te;
COUNT(*)
----------
100516
SYS@anqing2(rac2)> create index idx_te_object_name on te(object_name);
Index created.
2.2查看索引的Blevel,可以通过DBA_INDEXES.Blevel获得
*-Tree level:depth of the index from its root block to its leaf blocks. A depth of 0 indicates that the root block and leaf block are the same.
--从root block到leaf block的深度.如果root block和leaf block在同一个块中那么Blevel=0
SYS@anqing2(rac2)> select index_name,blevel from dba_indexes where index_name='IDX_TE_OBJECT_NAME';
INDEX_NAMEBLEVEL
------------------------------ ----------
IDX_TE_OBJECT_NAME2
2.3查看索引的height,索引的高度等于Blevel+1,height可以通过INDEX_STATS获得
SYS@anqing2(rac2)> select name,height from index_stats where name='IDX_TE_OBJECT_NAME';
no rows selected
--- index_stats需要analyze ... validate structure收集一下,否则无数据
SYS@anqing2(rac2)>analyze index IDX_TE_OBJECT_NAME validate structure;
Index analyzed.
SYS@anqing2(rac2)>select name,height from index_stats where name='IDX_TE_OBJECT_NAME';
NAMEHEIGHT
------------------------------ ----------
IDX_TE_OBJECT_NAME3
2.4 dump index
Oracle提供了分析Btree index结构的命令treedump,在进行treedump之前需要获得索引的object_id
SYS@anqing2(rac2)> select object_id from dba_objects where object_name='IDX_TE_OBJECT_NAME' and owner='SYS';
OBJECT_ID
----------
54769
SYS@anqing2(rac2)>oradebug setmypid
Statement processed.
SYS@anqing2(rac2)>alter session set events 'immediate trace name treedump level 54769';
Session altered.
SYS@anqing2(rac2)>oradebug tracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
2.5查看treedump trace文件
[oracle@rac2 ~]$ cat /u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
/u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:Linux
Node name:rac2
Release:2.6.18-194.el5
Version:#1 SMP Tue Mar 16 21:52:43 EDT 2010
Machine:i686
Instance name: anqing2
Redo thread mounted by this instance: 2
Oracle process number: 29
Unix process pid: 3865, image: oracle@rac2 (TNS V1-V3)
*** 2011-06-27 13:15:00.375
*** ACTION NAME:() 2011-06-27 13:15:00.371
*** MODULE NAME:(sqlplus@rac2 (TNS V1-V3)) 2011-06-27 13:15:00.371
*** SERVICE NAME:(SYS$USERS) 2011-06-27 13:15:00.371
*** SESSION ID:(130.55497) 2011-06-27 13:15:00.371
----- begin tree dump
branch: 0x4117c2 4265922 (0: nrow: 2, level: 2)
branch: 0x412086 4268166 (-1: nrow: 250, level: 1)
leaf: 0x4117c3 4265923 (-1: nrow: 182 rrow: 182)
leaf: 0x4117c4 4265924 (0: nrow: 182 rrow: 182)
leaf: 0x4117c5 4265925 (1: nrow: 186 rrow: 186)
leaf: 0x4117c6 4265926 (2: nrow: 189 rrow: 189)
leaf: 0x4117c7 4265927 (3: nrow: 186 rrow: 186)
leaf: 0x4117c8 4265928 (4: nrow: 190 rrow: 190)
leaf: 0x4117c9 4265929 (5: nrow: 186 rrow: 186)
leaf: 0x4117ca 4265930 (6: nrow: 178 rrow: 178)
leaf: 0x4117cb 4265931 (7: nrow: 187 rrow: 187)
leaf: 0x4117cc 4265932 (8: nrow: 182 rrow: 182)
......
leaf: 0x412080 4268160 (244: nrow: 222 rrow: 222)
leaf: 0x412081 4268161 (245: nrow: 201 rrow: 201)
leaf: 0x412082 4268162 (246: nrow: 240 rrow: 240)
leaf: 0x412083 4268163 (247: nrow: 226 rrow: 226)
leaf: 0x412084 4268164 (248: nrow: 211 rrow: 211)
branch: 0x41227b 4268667 (0: nrow: 245, level: 1)
leaf: 0x412085 4268165 (-1: nrow: 229 rrow: 229)
leaf: 0x412087 4268167 (0: nrow: 218 rrow: 218)
leaf: 0x412088 4268168 (1: nrow: 231 rrow: 231)
leaf: 0x412109 4268297 (2: nrow: 249 rrow: 249)
......
leaf: 0x412278 4268664 (241: nrow: 191 rrow: 191)
leaf: 0x412279 4268665 (242: nrow: 180 rrow: 180)
leaf: 0x41227a 4268666 (243: nrow: 56 rrow: 56)
----- end tree dump
2.6解释treedump输出
branch表示的是branch block,它后面跟了一个十六进制表示的DBA(data block address),以及用10进制表示的DBA。
DBA之后表示在同一层次的相对位置(root从0开始,branch以及leaf从-1开始)
nrow表示块中包含了多少条目(包括delete的条目)
rrow表示块中包含的实际条目(不包括delete的条目)
level表示从该block到leaf的深度(leaf没有level)
2.6.1branch: 0x4117c2 4265922 (0: nrow: 2, level: 2)说明
这个branch block的level为2,也就是说从这个branch block到leaf block的深度为2,根据前面的查询,这个索引的Blevel为2,所以这个branch其实是root block.其实根据nrow:2也可以看出来它是root block,因为nrow:2说明它只包含了2个条目,那么这2个条目其实就是dump文件中的其他2个branch block的条目
现在我来验证一下branch: 0x4117c2 4265922 (0: nrow: 2, level: 2)是不是root block ,我查询这个branch的DBA。
SYS@anqing2(rac2)>select dbms_utility.data_block_address_file('4265922') FILE_ID,dbms_utility.data_block_address_block('4265922') BLOCK_ID from dual;
FILE_IDBLOCK_ID
---------- ----------
171618
Btree索引的root block总是segment header+1,所以我查询该索引的段头
SYS@anqing2(rac2)>select header_file,header_block from dba_segments where segment_name='IDX_TE_OBJECT_NAME';
HEADER_FILE HEADER_BLOCK
----------- ------------
171617
那么现在已经证明了branch: 0x4117c2 4265922 (0: nrow: 2, level: 2)是root block,其实treedump第一个branch block就是root block。
2.6.2branch: 0x4120864268166(-1: nrow: 250, level: 1)说明
这个branch的DBA为0x412086(十六进制),4268166(十进制),-1表示它是与它在同一个深度的branch block中的第一个branch block。
nrow: 250:表示它有247个leaf block.
level: 1:表示这个branch block到leaf block的深度为1
2.6.3 leaf:0x4117c3 4265923(-1: nrow: 182 rrow: 182)说明
leaf表示它是一个leaf block 0x4117c3 4265923分别是这个leaf block的十六进制/十进制的DBA.
-1表示它是leaf block中的第一个block
nrow: 182表示它一共有182条记录
rrow: 182表示它实际有182条记录
2.7branch block dump
这里选择dump branch:branch: 0x412086 4268166 (-1: nrow: 250, level: 1)
SYS@anqing2(rac2)>select dbms_utility.data_block_address_file('4268166') FILE_ID,dbms_utility.data_block_address_block('4268166') BLOCK_ID from dual;
FILE_IDBLOCK_ID
---------- ----------
173862
SYS@anqing2(rac2)>oradebug tracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
--先清空一下
[oracle@rac2 ~]$cat /dev/null > /u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
SYS@anqing2(rac2)>alter system dump datafile 1 block 73862;
System altered.
2.7.1部分DUMP文件
[oracle@rac2 ~]$cat /u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
*** 2011-06-27 14:35:54.038
Start dump data blocks tsn: 0 file#: 1 minblk 73862 maxblk 73862
buffer tsn: 0 rdba: 0x00412086 (1/73862)
scn: 0x0000.004e24ec seq: 0x02 flg: 0x04 tail: 0x24ec0602
frmt: 0x02 chkval: 0x3371 type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0E707400 to 0x0E709400
E707400 0000A206 00412086 004E24EC 04020000[..... A..$N.....]
......
E7093F0 00000000 00000000 00000000 24EC0602[...............$]
Block header dump:0x00412086
Object id on Block? Y
seg/obj: 0xd5f1csc: 0x00.4e24c9itc: 1flg: -typ: 2 - INDEX
fsl: 0fnx: 0x0 ver: 0x01
ItlXidUbaFlagLckScn/Fsc
0x010xffff.000.000000000x00000000.0000.00C---0scn 0x0000.004e24c9
Branch block dump
=================
header address 242250820=0xe707444
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 249
kdxcofbo 526=0x20e
kdxcofeo 557=0x22d
kdxcoavs 31
kdxbrlmc 4265923=0x4117c3
kdxbrsno 0
kdxbrbksz 8056
kdxbr2urrc 0
row#0[8023] dba: 4265924=0x4117c4
col 0; len 24; (24):
2f 31 30 64 65 32 32 63 36 5f 43 6c 61 73 73 54 79 70 65 49 6d 70 6c 32
col 1; len 3; (3):00 41 1b
row#1[7984] dba: 4265925=0x4117c5
col 0; len 30; (30):
2f 31 31 64 35 30 39 31 32 5f 44 61 74 65 46 6f 72 6d 61 74 5a 6f 6e 65 44
61 74 61 5f 7a
col 1; len 3; (3):00 41 1c
row#2[7973] dba: 4265926=0x4117c6
col 0; len 5; (5):2f 31 32 61 32
col 1; TERM
row#3[7931] dba: 4265927=0x4117c7
col 0; len 30; (30):
2f 31 33 38 35 32 32 37 66 5f 4d 61 70 52 65 67 69 6f 6e 43 6f 6e 74 61 69
6e 6d 65 6e 74
col 1; len 6; (6):00 41 18 d5 00 08
......
row#247[571] dba: 4268163=0x412083
col 0; len 6; (6):41 4c 4c 5f 45 56
col 1; TERM
row#248[557] dba: 4268164=0x412084
col 0; len 8; (8):41 4c 4c 5f 4d 50 5f 50
col 1; TERM
----- end of branch block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 73862 maxblk 73862
[oracle@rac2 ~]$
2.7.2解释部分dump输出
kdxcolev1--该block到leaf block的深度(leaf block为0).这里branch block的level为1与前面查询相吻合
KDXCOLEV Flags = - - -
kdxcolok0--表示是否有事务lock了这个branch block,如果有,有多少事务
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco2--索引值条目.这里表示有2个条目
kdxcosdc0--这个block的结构被更改次数.这里0表示没有更改
kdxconro249 --索引条目(不包含kdxbrlmc指针)
kdxcofbo526=0x20e--空闲空间的起始偏移量
kdxcofeo557=0x22d--空闲空间的末尾偏移量
kdxcoavs31--block中的空闲空间=kdxcofeo-kdxcofbo
kdxbrlmc 4265923=0x4117c3 --如果index value小于row#0,指向该block的地址
kdxbrsno0--最后被更改的索引条目
kdxbrbksz 8056 --块中的可用空间
kdxbr2urrc 0
row#0[8023] dba: 4265924=0x4117c4--row#表示索引条目数,从0开始,紧接着就是十进制和十六进制的DBA,该DBA指向leaf block
col 0; len 24; (24):--列的行号,从0开始,紧接着的就是列的长度以及列的值,那么这个值称之为separator key,这个separator key可以区分真实的索引值,所以从这里我们也知道branch block不会存储完整的索引值,只要能区分就行
2f 31 30 64 65 32 32 63 36 5f 43 6c 61 73 73 54 79 70 65 49 6d 70 6c 32
col 1; len 3; (3):00 41 1b
2.8leaf block DUMP
这里选择row#247[571] dba: 4268163=0x412083,因为它包含的索引键很少
row#247[571]dba: 4268163=0x412083
col 0; len 6; (6):41 4c 4c 5f 45 56
col 1; TERM
dump之前先看一下row#247[571]存储的'41 4c 4c 5f 45 56'是什么索引键.使用如下代码转换:
SQL> set serveroutput on
/* Formatted on 2011/6/27 16:53:27 (QP5 v5.163.1008.3004) */
DECLARE
nVARCHAR2(2000);
BEGIN
DBMS_STATS.convert_raw_value('41',n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('4c',n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('4c',n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('5f',n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('45',n);
DBMS_OUTPUT.put_line(n);
DBMS_STATS.convert_raw_value('46',n);
DBMS_OUTPUT.put_line(n);
END;
这个键值代表:
A
L
L
_
E
F
--查看file_id和block_id
SYS@anqing2(rac2)>select dbms_utility.data_block_address_file('4268163') FILE_ID,dbms_utility.data_block_address_block('4268163')BLOCK_ID from dual;
FILE_IDBLOCK_ID
---------- ----------
173859
SYS@anqing2(rac2)>alter system dump datafile 1 block 73859;
System altered.
SYS@anqing2(rac2)>oradebug tracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
2.8.1部分DUMP文件
[oracle@rac2 ~]$cat /u01/app/oracle/admin/anqing/udump/anqing2_ora_3865.trc
*** 2011-06-27 17:00:01.805
Start dump data blocks tsn: 0 file#: 1 minblk 73859 maxblk 73859
buffer tsn: 0 rdba: 0x00412083 (1/73859)
scn: 0x0000.004e24ec seq: 0x02 flg: 0x04 tail: 0x24ec0602
frmt: 0x02 chkval: 0xb42b type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0E707400 to 0x0E709400
E707400 0000A206 00412083 004E24EC 04020000[..... A..$N.....]
......
E7093F0 00000000 00000000 00000000 24EC0602[...............$]
Block header dump:0x00412083
Object id on Block? Y
seg/obj: 0xd5f1csc: 0x00.4e24c9itc: 2flg: -typ: 2 - INDEX
fsl: 0fnx: 0x0 ver: 0x01
ItlXidUbaFlagLckScn/Fsc
0x010x0000.000.000000000x00000000.0000.00----0fsc 0x0000.00000000
0x020xffff.000.000000000x00000000.0000.00C---0scn 0x0000.004e24c9
Leaf block dump
===============
header address 242250844=0xe70745c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 226
kdxcofbo 488=0x1e8
kdxcofeo 1324=0x52c
kdxcoavs 836
kdxlespl 0
kdxlende 0
kdxlenxt 4268164=0x412084
kdxleprv 4268162=0x412082
kdxledsz 0
kdxlebksz 8032
row#0[7999] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 45 56 41 4c 55 41 54 49 4f 4e 5f 43 4f 4e 54 45 58 54 53
col 1; len 6; (6):00 41 1a 71 00 2a
row#1[7966] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 45 56 41 4c 55 41 54 49 4f 4e 5f 43 4f 4e 54 45 58 54 53
col 1; len 6; (6):00 41 1a 71 00 2b
row#2[7933] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 45 56 41 4c 55 41 54 49 4f 4e 5f 43 4f 4e 54 45 58 54 53
col 1; len 6; (6):00 43 eb 77 00 3d
......
row#224[1357] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 4d 50 5f 47 52 41 50 48 5f 57 4f 52 4b 53 50 41 43 45 53
col 1; len 6; (6):00 41 1a ad 00 18
row#225[1324] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 4d 50 5f 47 52 41 50 48 5f 57 4f 52 4b 53 50 41 43 45 53
col 1; len 6; (6):00 41 1a ad 00 19
----- end of leaf block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 73859 maxblk 73859
[oracle@rac2 ~]$
2.8.2解释部分dump输出
kdxcolev0--该block到leaf block的深度(leaf block为0).
KDXCOLEV Flags = - - -
kdxcolok0--表示是否有事务lock了这个branch block,如果有有多少事务
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco2--索引值条目.这里表示有2个条目
kdxcosdc 0--这个block的结构被更改次数.这里0表示没有更改
kdxconro 226--索引条目,这里有189个索引条目它等于row#225-row#0+1
kdxcofbo 488=0x1e8--空闲空间的起始偏移量
kdxcofeo 1324=0x52c--空闲空间的末尾偏移量
kdxcoavs 836--block中的空闲空间=kdxcofeo-kdxcofbo
kdxlespl 0--block split的时候没有commit的记录的大小(byte)
kdxlende 0--被删除的条目
kdxlenxt 4268164=0x412084--指向下一个leaf block的指针(DBA)
kdxleprv 4268162=0x412082--指向上一个leaf block的指针(DBA)
kdxledsz 0--被删除的空间
kdxlebksz 8032 --可用空间
row#0[7999] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 45 56 41 4c 55 41 54 49 4f 4e 5f 43 4f 4e 54 45 58 54 53
col 1; len 6; (6):00 41 1a 71 00 2a
row#表示索引值的条目,从0开始lock: 0表示ITL中的锁信息0表示没有被锁len=33表示索引值长度
col表示列号,从0开始那么接下来就是索引的键值以及rowid中后23位值。
即:col 0是键值,col 1是rowid
下面我们来看一下row#0存储的值是什么,先看col 0的键值:
SYS@anqing2(rac2)> declare n varchar2(2000);
2begin
3dbms_stats.convert_raw_value('414c4c5f4556414c554154494f4e5f434f4e5445585453',n);
4dbms_output.put_line(n);
5end;
6/
ALL_EVALUATION_CONTEXTS
查看col1 rowid的值:
ROWID一共用18位表示:
最前6位表示data object number
之后后3位表示datafile number
之后后6位表示datablock number
最后3位表示row number
有关rowid更多内容,参考Blog:
Oracle Rowid介绍
http://blog.youkuaiyun.com/xujinyang/article/details/6829751
SYS@anqing2(rac2)>select to_number('00411a71','xxxxxxxxxxxxxxxx') from dual;
TO_NUMBER('00411A71','XXXXXXXXXXXXXXXX')
----------------------------------------
4266609
这里的rowid其实是除去了data object number的一部分而已。即col 1中6位中的前4位。
SYS@anqing2(rac2)>select dbms_utility.data_block_address_file('4266609') FILE_ID,dbms_utility.data_block_address_block('4266609') BLOCK_ID from dual;
FILE_IDBLOCK_ID
---------- ----------
172305
SYS@anqing2(rac2)> select dbms_rowid.rowid_relative_fno(rowid)file_id, dbms_rowid.rowid_block_number(rowid)block_id,dbms_rowid.rowid_row_number(rowid) row#from te whereobject_name='ALL_EVALUATION_CONTEXTS';
FILE_IDBLOCK_IDROW#
---------- ---------- ----------
17230542
17230543
125688761
125688762
根据这个还原的值我来查询一下
SYS@anqing2(rac2)>select owner,object_name,rowid from te where object_name='ALL_EVALUATION_CONTEXTS';
OWNEROBJECT_NAMEROWID
---------- ------------------------- ------------------
SYSALL_EVALUATION_CONTEXTSAAANXwAABAAARpxAAq
PUBLICALL_EVALUATION_CONTEXTSAAANXwAABAAARpxAAr
SYSALL_EVALUATION_CONTEXTSAAANXwAABAAA+t3AA9
PUBLICALL_EVALUATION_CONTEXTSAAANXwAABAAA+t3AA+
SYS@anqing2(rac2)>select owner,object_name,dump(rowid,16) from te where object_name='ALL_EVALUATION_CONTEXTS';
OWNEROBJECT_NAMEDUMP(ROWID,16)
---------- ------------------------- -------------------------------------------
SYSALL_EVALUATION_CONTEXTSTyp=69 Len=10: 0,0,d5,f0,0,41,1a,71,0,2a
PUBLICALL_EVALUATION_CONTEXTSTyp=69 Len=10: 0,0,d5,f0,0,41,1a,71,0,2b
SYSALL_EVALUATION_CONTEXTSTyp=69 Len=10: 0,0,d5,f0,0,43,eb,77,0,3d
PUBLICALL_EVALUATION_CONTEXTSTyp=69 Len=10: 0,0,d5,f0,0,43,eb,77,0,3e
在看一下,在2.8节开始的branch block信息:
row#247[571] dba: 4268163=0x412083
col 0; len 6; (6):41 4c 4c 5f 45 56
col 1; TERM
其中col 0,我们转换之后是:ALL_EF,由此可见,col 0是真正的索引键的前缀。
它是每个具体键值的前一部分,即col0的一部分。如:
row#0[7999] flag: ------, lock: 0, len=33
col 0; len 23; (23):
41 4c 4c 5f 45 56 41 4c 55 41 54 49 4f 4e 5f 43 4f 4e 54 45 58 54 53
col 1; len 6; (6):00 41 1a 71 00 2a
Oracle在Branch block中只记录索引键值的前缀,而不是所有值,是因为这样可以节约空间,从而能够存储更多的索引条目。
同时,我们也能理解了为什么查询使用like '%xxx'这种方法不会走Btree索引,因为Branch block存储的是前缀.
说明:
根据robinson的blog,重新做的测试,原文链接如下:
http://blog.youkuaiyun.com/robinson1988/archive/2011/01/04/6116276.aspx
-------------------------------------------------------------------------------------------------------