当前位置: 代码迷 >> 综合 >> 怎么将dump 出来的 bitmap index 中的rowid 还原回 file_id,block_id
  详细解决方案

怎么将dump 出来的 bitmap index 中的rowid 还原回 file_id,block_id

热度:27   发布时间:2023-12-14 21:28:11.0

今天在研究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

  相关解决方案