Oracle B-Tree Index 原理

 

. B-Tree Index 原理

官网说明:

       No index structure can satisfy all needs, but the 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 in Figure 7-1 has 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 the Knuth variation in 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.csdn.net/tianlesoftware/archive/2011/06/07/6529346.aspx

 

       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 * from  dba_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_NAME                         BLEVEL

------------------------------ ----------

IDX_TE_OBJECT_NAME                      2

 

2.3 查看索引的height,索引的高度等于Blevel+1height可以通过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';

NAME                               HEIGHT

------------------------------ ----------

IDX_TE_OBJECT_NAME                      3

 

 

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 表示从该blockleaf的深度(leaf没有 level) 

 

2.6.1  branch: 0x4117c2 4265922 (0: nrow: 2, level: 2) 说明

       这个 branch block level 2,也就是说 从这个branch block leaf block 的深度为2,根据前面的查询,这个索引的Blevel2,所以这个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_ID   BLOCK_ID

---------- ----------

         1      71618

 

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

----------- ------------

          1        71617

 

       那么现在已经证明了 branch: 0x4117c2 4265922 (0: nrow: 2, level: 2) root block, 其实 treedump第一个 branch block 就是 root block

 

 

2.6.2  branch: 0x412086 4268166 (-1: nrow: 250, level: 1)  说明

       这个branch DBA0x412086 (十六进制)4268166 (十进制) -1 表示它是与它在同一个深度的 branch block中的第一个 branch block 

       nrow: 250 :表示它有247 leaf block.

       level: 1 :表示 这个 branch block leaf block的深度为

 

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.7  branch 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_ID   BLOCK_ID

---------- ----------

         1      73862

 

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: 0xd5f1  csc: 0x00.4e24c9  itc: 1  flg: -  typ: 2 - INDEX

     fsl: 0  fnx: 0x0 ver: 0x01

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 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输出 

 

kdxcolev 1  --blockleaf block的深度(leaf block 0).这里branch block level 1 与前面查询相吻合  

KDXCOLEV Flags = - - - 

kdxcolok 0  --表示是否有事务lock了这个branch block,如果有,有多少事务 

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

kdxconco 2  --索引值条目. 这里表示有2个条目 

kdxcosdc--这个block的结构被更改次数.这里0表示没有更改 

kdxconro 249 --索引条目(不包含kdxbrlmc 指针

kdxcofbo 526=0x20e  --空闲空间的起始偏移量

kdxcofeo 557=0x22d  --空闲空间的末尾偏移量

kdxcoavs 31  --block中的空闲空间=kdxcofeo-kdxcofbo 

kdxbrlmc 4265923=0x4117c3 --如果index value小于row#0,指向该 block 的地址 

kdxbrsno 0   --最后被更改的索引条目 

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.8  leaf 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

   n   VARCHAR2 (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_ID   BLOCK_ID

---------- ----------

         1      73859

 

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: 0xd5f1  csc: 0x00.4e24c9  itc: 2  flg: -  typ: 2 - INDEX

     fsl: 0  fnx: 0x0 ver: 0x01

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

0x02   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 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输出

kdxcolev 0  --blockleaf block的深度(leaf block 0). 

KDXCOLEV Flags = - - - 

kdxcolok 0   --表示是否有事务lock了这个branch block,如果有 有多少事务 

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

kdxconco 2   --索引值条目. 这里表示有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); 

  2  begin 

  3  dbms_stats.convert_raw_value('414c4c5f4556414c554154494f4e5f434f4e5445585453',n); 

  4  dbms_output.put_line(n); 

  5  end; 

  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.csdn.net/tianlesoftware/archive/2009/12/16/5020718.aspx

 

SYS@anqing2(rac2)> select to_number('00411a71','xxxxxxxxxxxxxxxx') from dual;  

TO_NUMBER('00411A71','XXXXXXXXXXXXXXXX')

----------------------------------------

              4266609 

 

       这里的rowid其实是除去了 data object number的一部分而已。 col 16位中的前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_ID   BLOCK_ID

---------- ----------

         1      72305 

 

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 where object_name='ALL_EVALUATION_CONTEXTS'; 

 

   FILE_ID   BLOCK_ID       ROW#

---------- ---------- ----------

         1      72305         42

         1      72305         43

         1     256887         61

         1     256887         62 

 

 

根据这个还原的值我来查询一下 

 

SYS@anqing2(rac2)> select owner,object_name,rowid from te where object_name='ALL_EVALUATION_CONTEXTS'; 

 

OWNER      OBJECT_NAME               ROWID

---------- ------------------------- ------------------

SYS        ALL_EVALUATION_CONTEXTS   AAANXwAABAAARpxAAq

PUBLIC     ALL_EVALUATION_CONTEXTS   AAANXwAABAAARpxAAr

SYS        ALL_EVALUATION_CONTEXTS   AAANXwAABAAA+t3AA9

PUBLIC     ALL_EVALUATION_CONTEXTS   AAANXwAABAAA+t3AA+

 

 

SYS@anqing2(rac2)> select owner,object_name,dump(rowid,16) from te where object_name='ALL_EVALUATION_CONTEXTS'; 

 

OWNER      OBJECT_NAME               DUMP(ROWID,16)

---------- ------------------------- -------------------------------------------

SYS      ALL_EVALUATION_CONTEXTS   Typ=69 Len=10: 0,0,d5,f0,0,41,1a,71,0,2a

PUBLIC     ALL_EVALUATION_CONTEXTS   Typ=69 Len=10: 0,0,d5,f0,0,41,1a,71,0,2b

SYS        ALL_EVALUATION_CONTEXTS   Typ=69 Len=10: 0,0,d5,f0,0,43,eb,77,0,3d

PUBLIC     ALL_EVALUATION_CONTEXTS   Typ=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.csdn.net/robinson1988/archive/2011/01/04/6116276.aspx

 

 

 

 

 

-------------------------------------------------------------------------------------------------------

Blog http://blog.csdn.net/tianlesoftware

Email: dvd.dba@gmail.com

DBA1 群:62697716();   DBA2 群:62697977()   DBA3 群:62697850()  

DBA 超级群:63306533();  DBA4 群: 83829929  DBA5群: 142216823   

DBA6 群:158654907  聊天 群:40132017   聊天2群:69087192

--加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请

 

转载于:https://www.cnblogs.com/hibernate315/archive/2011/06/27/2399002.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

曾改变世界的最强科学,为什么我们对它的误解却越来越多?

古往今来,我们评价一个人有学识,总是形容:“上知天文下知地理”。也会要求一个人“读万卷书,行万里路”。美国认知心理学家Nora S. Newcombe认为:孩子常常看地图、爱看地图,能提高他们的空间想象力&#xf…

多线程环境下,程序真是危机四伏

姿势在不断的更新迭代, 太卷了。你管这也叫线程安全?最近大意了,竟然想将《面试官:实现一个带值变更通知能力的Dictionary》一文中的临界锁只应用到写操作。内心旁白:读操作又不会修改数据,无论是新值还是旧…

眼见不一定为实!18个神奇的视错觉,看完不相信眼睛系列

全世界只有3.14 % 的人关注了爆炸吧知识来源:普象工业设计小站在家长时间网上冲浪总有时候感觉眼睛出了毛病不信,你看为啥这个明明是个三棱锥怎么突然变成了正方体我是“瞎”了么啊啊啊啊后来,去找了资料才发现这原来是一家幻觉博物馆的展品玩…

怎么用java ee编程_Java EE应用程序入门 - 编程入门网

Java EE应用程序入门时间:2011-07-06 netbeans.org本文将详细介绍使用 EJB 3.0 技术开发企业应用程序的基础知识,而 EJB 3.0 是 Java EE 5 平台的组成部分。本文还将阐述如何通过 EJB 3.0 技术简化开发企业应用程序的流程。本文使用的是 NetBeans IDE 6.0 发行版。先…

vb6 由于超出容量限制 不能创建新事务_分布式限流?你也能轻松玩转(没啥新技术)...

点击蓝色「日拱一兵」关注,持续侦破 Java 技术案件一、什么是限流?为什么要限流?不知道大家有没有做过帝都的地铁,就是进地铁站都要排队的那种,为什么要这样摆长龙转圈圈?答案就是为了限流!因为…

Managing Gigabytes--文本压缩

开门见山,文本压缩可以归纳为两大类, 符号方法和字典方法, 下面分别介绍下: 1)符号方法,symbolwise method普通编码方式是每个字符都采用相同位数编码, 比如asc码, 每个字符都是8位编码。那么现…

基于事件驱动架构构建微服务第8部分:在应用程序上实现事件溯源

原文链接:https://logcorner.com/building-microservices-through-event-driven-architecture-part8-implementing-eventsourcing-on-application/在本文中,我将讨论应用程序上的事件溯源实现。该层围绕领域并实现用例(特定于应用程序的业务规…

我们来聊点成年人的话题!

1 这个话题透漏着成年人都存在的问题,其中心思想行走在道德底线,让人不得不深思,句句入心2 哈哈哈哈哈哈哈哈哈哈哈哈哈画面惊人 图自动漫次元酱3 对不起,我不是你家的鸡,我是一只大鸟!!&#x…

yum安装最新的 LNMP

2019独角兽企业重金招聘Python工程师标准>>> 先添加几个源: rpm -Uvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-1.noarch.rpm rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm 1,安装nginx&a…

C#新版本风格项目文件(SDK风格项目 SDK-style project)

在VisualStudio中创建NetCore以上版本的项目,使用的都是新版本风格的项目文件。和旧版本.NetFramework版本的项目文件区别:双击项目可直接打开csproj文件进行编辑配置项目文件内容的改变项目属性文件夹图标更改项目引用去除,改成依赖项Nuget包…

史上最丧心病狂的商品定价套路:如何从数学角度,榨干你身上的每一分钱

全世界只有3.14 % 的人关注了爆炸吧知识世上没有精明的买家,只有精明的卖家。的确,卖家的嘴,骗人的鬼。在买与卖的博弈中,没有一个买家可以取胜。别不信,今天就让你见识下“卖家套路终极奥义”。按量定价,是…

东北大姐剪纸被误认为油画,遭人质疑二十多年,只因太过逼真,看完后:真香!不愧是天下第一剪!...

全世界只有3.14 % 的人关注了爆炸吧知识“这是剪纸?太惟妙惟肖了,我还以为是水彩画呢!”这是一位网友的留言。茂盛的树木、潺潺的流水……这些栩栩如生的场景,真难想象竟是出自,一双巧手和一把剪刀。这些作品,全部来自…

2021 年 9 月 TIOBE 指数 C# 同比增长突破 1.2%

TIOBE 编程社区指数是编程语言流行程度的指标。该指数每月更新一次。评级基于全球熟练工程师、课程和第三方供应商的数量。谷歌、必应、雅虎、维基百科、亚马逊、YouTube 和百度等流行搜索引擎用于计算评分。C# 近期发展状态不错,依旧在榜单中排第五,但排…

2010年5月系统集成项目管理工程师上午试卷参考答案(讨论版)

鉴于个人精力有限,其他答案将由51CTO相关工作人员不断更新,详见http://training.51cto.com/art/201005/200323.htm以题会友,欢迎跟贴拍砖、讨论。

那些35岁的程序员都去哪了

阅读本文大概需要11分钟。大家好,我是findyi,前段时间写过一篇关于大龄程序员的文章:那些40岁的程序员都去哪了,引发了大家的思考和讨论,不少读者私聊问:除了这些出路,还有没有其他可能&#xf…

Sharepoint学习笔记---如何在Sharepoint2010网站中整合Crystal Report水晶报表(显示数据 二)...

在Sharepoint学习笔记---如何在Sharepoint2010网站中整合Crystal Report水晶报表(显示数据一)中,解释了如何把Crystal Report整合到Sharepoint2010并把报表数据显示出来,但这样并不完整,因为我们在开发时是以系统帐户进…

那些拧不开瓶盖的女生全都是装的?理工男这样想......

全世界只有3.14 % 的人关注了爆炸吧知识昨天,超模君我正在思考人生,八岁的表妹突然提着一瓶矿泉水站在了我的面前。她可怜兮兮的说:“我想喝水,但是拧不开”。我:“........."超模君我明明亲眼见过她一口气拧开过…

【另类见解】秒杀并非高不可攀

“一提到秒杀很简单这个话题,我知道要被别人鄙视了:你不懂高并发... 这年头开头不画个思维导图都觉得掉价image谈到秒杀,网络上不少于几千片文章,但是大多大同小异。如果你的微信当中关注了几个编程技术类的公众号,我敢…

我又相信爱情了!

1 圣诞限定款的肥宅快乐水更好喝了吗?不!更贵了2 周边鬼才!这手机壳我爱了3 你以为是个王者,其实是个大脸......4 高温超导材料达到临界温度后能使物体悬浮在不同位置5 火山爆发你见过吗?6 我又相信爱情了!…

opencv计算两数组的乘积_#剑指Offer#12. 构建乘积数组

题目描述:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1]。其中B中的元素B[i]A[0] * A[1]... * A[i-1] * A[i1]... * A[n-1]。不能使用除法。解题思路:首先,仔细理解题意,B[i]是A数组所有元素的乘积,但是没…