怎么将dump 出来的 bitmap index 中的rowid 还原回 file_id,block_id
转自 http://blog.csdn.net/robinson1988/article/details/5396595
今天在研究Bitmap Index internal的东东,不过刚开始就被卡住了,dump出来了bitmap index 根据DSI知道有个叫start rowid,end rowid的东东,却不能将rowid还原回file_id,block_id。现在终于搞懂了呵呵,写出来分享下。哎,前面的路还很长,很长..................
SQL> create table test(name varchar2(100),age number);
表已创建。
SQL> insert into test values('Robinson',20);
已创建 1 行。
SQL> insert into test values('Luobingsen',20);
已创建 1 行。
SQL> insert into test values('Luo, Bing-Sen',22);
已创建 1 行。
SQL> insert into test values('MR.Robinson',22);
已创建 1 行。
SQL> commit;
提交完成。
SQL> select distinct dbms_rowid.rowid_block_number(rowid) from test;
DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
30
可以看见这些数据都存储在同一个block中。
SQL> 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 test;
FILE_ID BLOCK_ID ROW#
---------- ---------- ----------
6 30 0
6 30 1
6 30 2
6 30 3
这些数据存储于datafile 6 blck 30中 并且为 0,1,2,3行
SQL> create bitmap index b_age on test(age);
索引已创建。
SQL> select segment_name,segment_type,file_id,block_id from dba_extents where segment_name='B_AGE';
SEGMENT_NA SEGMENT_TY FILE_ID BLOCK_ID
---------- ---------- ---------- ----------
B_AGE INDEX 6 33
SQL> select segment_name,blocks from dba_segments where segment_name='B_AGE';
SEGMENT_NAME BLOCKS
-------------------------------------------------------------------------------- ----------
B_AGE 8
SQL> alter system dump datafile 6 block min 33 block max 40;
系统已更改。
部分DUMP文件
Leaf block dump
===============
header address 166208100=0x9e82264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 2
kdxcofbo 40=0x28
kdxcofeo 7992=0x1f38
kdxcoavs 7952
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8014] flag: ------, lock: 0, len=22
col 0; len 2; (2): c1 15 ---这里表示20
col 1; len 6; (6): 01 80 00 1e 00 00 -- 这里 表示start rowid
col 2; len 6; (6): 01 80 00 1e 00 07 -- 这里 表示end rowid
col 3; len 2; (2): c8 03 这个暂时不讨论 这篇博客是讲的 怎么讲 rowid还原回file_id,block_id,row#
row#1[7992] flag: ------, lock: 0, len=22
col 0; len 2; (2): c1 17
col 1; len 6; (6): 01 80 00 1e 00 00
col 2; len 6; (6): 01 80 00 1e 00 07
col 3; len 2; (2): c8 0c
----- end of leaf block dump -----
由前面可知 file_id应该是 6 block_id应该是30,如何将ROWID还原回去呢?
其实我们要知道ROWID的组成原理,这里的ROWID非标准的ROWID,这里的ROWID没有记录object#,只记录了file_id,
block_id,row#.
其实我们只需要取rowid的前八位就能得到file_id,block_id
SQL> select to_number('0180001e','xxxxxxxxxxxx') from dual;
TO_NUMBER('0180001E','XXXXXXXXXXXX')
------------------------------------
25165854
SQL> select dbms_utility.data_block_address_file('25165854') FILE_ID,dbms_utility.data_block_address_block('25165854') BLOCK_ID from dual;
FILE_ID BLOCK_ID
---------- ----------
6 30
为什么这样就能够得到file_id,block_id呢,其实这个原理和DBA(data block address)的原理是一样的。通常我们dump一个block就能看见DBA(16位表示)信息,这个DBA信息就记录了file_id,block_id的信息,它是用前10位表示file_id,后22位表示block_id,所以这里还有种方法可以将rowid还原回file_id,block_id。方法就是将01 80 00 转换为2进制,取二进制前10位换算成十进制就是6,后面的22位就是30