oracle的B-tree索引结构分析

软件版本:XP sp2,Oracle 10.2.0.1

首先创建测试表:

SQL> create table test_idx
2 as
3 select * from all_objects
4 /

表已创建。


SQL> select count(*) from test_idx;

COUNT(*)
--------------
4473

SQL> desc test_idx
名称 是否为空? 类型
---------------------------------- --------------- --------------
OWNER NOT NULL VARCHAR2(30)
OBJECT_NAME NOT NULL VARCHAR2(30)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ID NOT NULL NUMBER
......

我们在整数列object_id上创建索引:

SQL> create index idxx on test_idx(object_id)
2 /

索引已创建。

查询新建的表和索引所在的表空间(因为自动段管理与手工管理的不同情况下,表空间中的段头所占用的block数是不同的,自动管理情况下,段头占用3个block,手工管理占用1个block):

SQL> select tablespace_name,segment_name
2 from user_segments
3 where segment_name in('TEST_IDX','IDXX')
4 /

TABLESPACE_NAME SEGMENT_NAME
------------------------------ ---------------
USERS TEST_IDX
USERS IDXX

查询users表空间的段空间管理方式:

SQL> conn system/oracle
已连接。
SQL> select tablespace_name,segment_space_management
2 from dba_tablespaces
3 where tablespace_name='USERS'
4 /

TABLESPACE_NAME SEGMEN
------------------------------ -------------
USERS AUTO


查询新建索引被分配的block情况:

SQL> col segment_name for a10
SQL> select segment_name,file_id,extent_id,block_id
2 from dba_extents
3 where segment_name='IDXX'
4 /

SEGMENT_NA FILE_ID EXTENT_ID BLOCK_ID
------------------- ------------- ---------------- ----------------
IDXX 4 0 225
IDXX 4 1 233

从上面结果可以知道,新建的索引分配到两个区,
各有8个block。因为索引所在的表空间为自动段管理,
其中的数据对象被分配的前三个block用来存储对象的
系统信息,而对象的真正数据从第4个block开始存储,
所以,idxx的数据228块开始存储。
下面,我们导出从228开始的三个数据块内容:

SQL> conn system/oracle
已连接。
SQL> alter system dump datafile 4 block min 228 block max 230;

系统已更改。

在udmp目录下查看新生成的导出文件,并打开,可以看出
228块为root节点,而229及230为两个叶节点。
摘录其内容如下(内容经过删减,但未作更改):

228号:

Branch block dump ---表明这是一个分枝节点,其实这是root节点=================
header address 121512524=0x73e224c
kdxcolev 1 ##index level (0 represents leaf blocks)
KDXCOLEV Flags = - - -
kdxcolok 0 ##denotes whether structural block transaction is occurring
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y ##internal operation code
kdxconco 2 ##index column count
kdxcosdc 0 ##count of index structural changes involving block
kdxconro 9 ##number of index entries (does not include kdxbrlmc pointer)
kdxcofbo 46=0x2e ##offset to beginning of free space within block
kdxcofeo 7979=0x1f2b ##offset to the end of free space (ie. first portion of block containing index data)
kdxcoavs 7933 ##available space in block (effectively area between the two fields above)
kdxbrlmc 16777445=0x10000e5 --这是下层节点的第 一个block号码 229

kdxbrsno 0 ##last index entry to be modified
kdxbrbksz 8060 ##size of usable block space
kdxbr2urrc 0
row#0[8051] dba: 16777446=0x10000e6 --块号230
col 0; len 3; (3): c2 12 30 --此块中的最小的key值
col 1; TERM
row#1[8042] dba: 16777447=0x10000e7 --块号
col 0; len 3; (3): c2 19 60 --此块中的最小的key值
col 1; TERM
row#2[8033] dba: 16777448=0x10000e8
col 0; len 3; (3): c2 21 5f
col 1; TERM
row#3[8024] dba: 16777449=0x10000e9
col 0; len 3; (3): c2 29 49
col 1; TERM
……

row#7[7988] dba: 16777453=0x10000ed
col 0; len 3; (3): c2 54 21
col 1; TERM
row#8[7979] dba: 16777454=0x10000ee
col 0; len 3; (3): c2 64 61
col 1; TERM
----- end of branch block dump -----

可以看出,root节点下层共有10个block

相关内容的解释:

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)


229号:

Leaf block dump
===============
header address 121512548=0x73e2264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 479
kdxcofbo 994=0x3e2
kdxcofeo 1813=0x715
kdxcoavs 819
kdxlespl 0
kdxlende 0
kdxlenxt 16777446=0x10000e6 --下一个block号码
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8023] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 03 3b --此块中的最小key值

col 1; len 6; (6): 01 00 00 a4 00 00 --rowid
row#1[8010] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 03 3c
col 1; len 6; (6): 01 00 00 a4 00 01
row#2[7997] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 04 0c
col 1; len 6; (6): 01 00 00 a4 00 02
……

row#477[1826] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 12 2e
col 1; len 6; (6): 01 00 00 a9 00 4f
row#478[1813] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 12 2f
col 1; len 6; (6): 01 00 00 aa 00 00
----- end of leaf block dump -----

230号:

Leaf block dump
===============
header address 121512548=0x73e2264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 479
kdxcofbo 994=0x3e2
kdxcofeo 1814=0x716
kdxcoavs 820
kdxlespl 0
kdxlende 0
kdxlenxt 16777447=0x10000e7 --下一个block号码

kdxleprv 16777445=0x10000e5 --前一个block号码

kdxledsz 0
kdxlebksz 8036
row#0[8023] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 12 30
col 1; len 6; (6): 01 00 00 aa 00 01
row#1[8010] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 12 31
col 1; len 6; (6): 01 00 00 aa 00 02
row#2[7997] flag: ------, lock: 0, len=13
col 0; len 3; (3): c2 12 33
col 1; len 6; (6): 01 00 00 aa 00 03
……

关于rowid的换算:索引中的rowid由48个bit构成,前10个bit构成文件号,中间22个bit构成块号,最后16个bit构成块中的行号。

关于整数key值的换算:如229块中的最小key值为c2 03 3b,先去掉c2,因为c2只表示最高位的位置,后面才是真正数据,03转换为十进制为3,减去1为2,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码,然后对应到相应字符。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/37724/viewspace-152533/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/37724/viewspace-152533/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值