声明:本篇知识体系受到dbsnake相关文章启发,特此感谢!
本系列的中篇(http://space.itpub.net/17203031/viewspace-700163)中,我们进行了Normal Index的导出和结构分析。分析后,我们发现Normal Index叶子节点实际上是表现为两个column结构,第一列为索引列值,第二列为对应rowid。本篇中,我们以相同的方法对unique index进行研究。
1、 Unique Index逻辑结构Dump
相似,使用Treedump的方法,将索引树idx_t_uniqueid进行导出。
--Unique Index
SQL> select name, value from v$diag_info where name='Default Trace File';
NAME VALUE
-------------------- --------------------------------------------------------------------------------
Default Trace File /u01/diag/rdbms/wilson/wilson/trace/wilson_ora_6330.trc
//75142为索引idx_t_uniqueid的object_id
SQL> alter session set events 'immediate trace name treedump level 75142';
Session altered
//Trace File中的核心片段如下:
*** 2011-06-15 02:16:41.584
*** SESSION ID:(138.4) 2011-06-15 02:16:41.584
*** CLIENT ID:() 2011-06-15 02:16:41.584
*** SERVICE NAME:(wilson) 2011-06-15 02:16:41.584
*** MODULE NAME:(PL/SQL Developer) 2011-06-15 02:16:41.584
*** ACTION NAME:(Command Window - New) 2011-06-15 02:16:41.584
----- begin tree dump
leaf: 0x415af9 4283129 (0: nrow: 3 rrow: 3)
----- end tree dump
由于该索引结构很小,只包括一个叶子节点索引块。该块地址的十六进为:0x415af9,对应十进制地址为4283129。查找对应的file编号和block编号。
SQL> select dbms_utility.data_block_address_file(4283129), dbms_utility. data_block_address_block(4283129) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRES DBMS_UTILITY.DATA_BLOCK_ADDRES
------------------------------ ------------------------------
1 88825
地址4283129对应的位置为file编号1,block编号88825。
使用数据块dump的方法,将数据块dump出。
SQL> alter system dump datafile 1 block 88825;
System altered
//Trace File中的内容
Start dump data blocks tsn: 0 file#:1 minblk 88825 maxblk 88825
Block dump from cache:
Dump of buffer cache at level 4 for tsn=0, rdba=4283129
BH (0x2afeef14) file#: 1 rdba: 0x00415af9 (1/88825) class: 1 ba: 0x2adf6000
set: 5 pool 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 55,19
(篇幅原因,省略部分……)
Block header dump: 0x00415af9
Object id on Block? Y
seg/obj: 0x12586 csc: 0x00.396f56 itc: 2 flg: - typ: 2 - INDEX
fsl: 0 fnx: 0x0 ver: 0x01
row#0[8021] flag: ------, lock: 0, len=11, data:(6): 00 41 5a e9 00 00
col 0; len 2; (2): c1 02
row#1[8010] flag: ------, lock: 0, len=11, data:(6): 00 41 5a e9 00 01
col 0; len 2; (2): c1 03
row#2[7999] flag: ------, lock: 0, len=11, data:(6): 00 41 5a e9 00 02
col 0; len 2; (2): c1 04
----- end of leaf block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 88825 maxblk 88825
此处,我们看到了Unique Index索引叶子节点和Normal Index的差异。在Unique Index叶子节点上,每行row只对应了一个col信息(而非normal index的两个)。Col[0]中对应的是索引列的键值。而rowid被放置在了行row的头部。这点差异就意味着两种索引结构在存储构成上的确有一些差距。
下面,我们来检查一下纯物理结构,借助BBED工具。
2、Unique Index物理结构分析
至此,我们已经知道了索引叶子块所在文件和块编号,进行物理分析只需要计算额外的offset偏移量。
从对unique index索引块dump出的结果看,我们可以看到相对偏移量信息。
row#2[7999] flag: ------, lock: 0, len=11, data:(6): 00 41 5a e9 00 02
col 0; len 2; (2): c1 04
----- end of leaf block dump -----
与对Normal Index相同,我们研究第三行数据,相对偏移量是7999。由于索引idx_t_uniqueid也存在在system表空间,属于MSSM管理方式。计算块内偏移量信息:
7999+68+(2-1)*24=8091
使用BBED的要素已经获取到,进行物理分析。
//设置文件和块号
BBED> set dba 0x00415af9
DBA 0x00415af9 (4283129 1,88825)
//设置偏移量
BBED> set offset 8091
OFFSET 8091
BBED> dump
File: /u01/oradata/WILSON/datafile/o1_mf_system_6bcsnqfc_.dbf (1)
Block: 88825 Offsets: 8091 to 8191 Dba:0x00415af9
------------------------------------------------------------------------
00000041 5ae90002 02c10400 0000415a e9000102 c1030000 00415ae9 000002c1
02100000 40110e00 02004011 0e000203 c20837ac 00011300 13000040 110e0001
0040110e 000103c2 0834ac00 01060006 00004011 0d000700 40110d00 0703c208
32010657 6f
<32 bytes per line>
对应原有的dump结果,可以清晰看到索引列键值和rowid信息。
row#2[7999] flag: ------, lock: 0, len=11, data:(6): 00 41 5a e9 00 02
col 0; len 2; (2): c1 04
----- end of leaf block dump ---
加上连带的四个0,可以看到保存的方式。Rowid在行头,以0x02开头的col[0]结构,保存索引列键值。对比原有的normal index结构,可以发现差距。为便于查看,normal index的结构如下:
//Normal Index叶子节点,DUMP显示出来
BBED> dump
File: /u01/oradata/WILSON/datafile/o1_mf_system_6bcsnqfc_.dbf (1)
Block: 88817 Offsets: 8088 to 8191 Dba:0x00415af1
------------------------------------------------------------------------
000002c1 04060041 5ae90002 000002c1 03060041 5ae90001 000002c1 02060041
5ae90000 0d000040 15000002 00401500 000203c2 085eac00 01150015 00004015
00000100 40150000 0103c208 5aac0001 11001100 0040110f 00090040 110f0009
03c20858 0106496f
<32 bytes per line>
Normal Index叶子节点长度为len=12,unique index长度为len=11。差异就是在于0x06的第二列col[1]标志位。
3、结论
唯一索引和普通索引在结构上存在差异,主要表现在存储结构和方式上。两者相比,唯一索引在体积上略小一点。但是从实际应用方面,唯一索引只是比普通索引增加了列值约束。其他如执行计划、效率没有过多的差别。
此时笔者想法有两个以为:
首先,Oracle在设计唯一索引的时候,为什么要选择这样的结构?在使用的时候有什么优势所在?
其次,唯一索引没有选择隐式的约束,这种结构类型如何实现唯一的效果?