这篇文章里我们粗浅的分析了bitmap index的结构,但是从我测试的结果来看,dump出的trace文件的结果我真是看不懂,莫名其妙,明显跟bbed dump和10608的结果不一致,不知道oracle这里是怎么弄的?
如下是完整的测试过程:
SQL> create table t1(id number);
Table created
SQL> create bitmap index idx_t1 on t1(id);
Index created
SQL> insert into t1 values(1);
1 row inserted
SQL> insert into t1 values(2);
1 row inserted
SQL> insert into t1 values(1);
1 row inserted
SQL> insert into t1 values(1);
1 row inserted
SQL> insert into t1 values(2);
1 row inserted
SQL> commit;
Commit complete
SQL> select /*+ full(t1) */id,dbms_rowid.rowid_relative_fno(rowid)||'_'||dbms_rowid.rowid_block_number(rowid)||'_'||dbms_rowid.rowid_row_number(rowid) location from t1;
ID LOCATION
---------- --------------------------------------------------------------------------------
1 10_66988_0
2 10_66988_1
1 10_66988_2
1 10_66988_3
2 10_66988_4
Dump上述bitmap index block,如下是dump出来的trace文件的内容:
row#0[7886] flag: ------, lock: 2, len=27
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 00 00 00 00 00
col 2; len 6; (6): 02 81
col 3; len 7; (7): f
row#1[7859] flag: ------, lock: 2, len=27
col 0; len 2; (2): c1 03
col 1; len 6; (6): 00 00 00 00 00 00
col 2; len 6; (6): 02 81
col 3; len 7; (7): f
从上述trace文件来看:对于键值为1(即c1 02)的bitmap index而言,其rowid的下限是0,上限是02 81
rowid的下限怎么可能是0呢?encoded bitmap看来起也明显不对呀?
这里rowid的上限倒是对的,如下所示:
SQL> exec sys.cdba('
.
The file is 10
The block is 66988
PL/SQL procedure successfully completed
我觉得这里trace文件明显不对,我们来做一个10608:
SQL> drop index idx_t1;
Index dropped
SQL> oradebug setmypid
Statement processed.
SQL> oradebug event 10608 trace name context forever,level 10
Statement processed.
SQL> create bitmap index caipra.idx_t1 on caipra.t1(id);
Index created.
SQL> oradebug event 10608 trace name context off
Statement processed.
SQL> oradebug tracefile_name
/u01/app/oracle/admin/ipratest/udump/ipratest_ora_856500.trc
$ cat /u01/app/oracle/admin/ipratest/udump/ipratest_ora_856500.trc
/u01/app/oracle/admin/ipratest/udump/ipratest_ora_856500.trc
Oracle Database
......省略部分内容
qerbiARwo: bitmap size is 8168
qerbiIPI default pctfree=10
qerbiIPI length=0
qerbiAllocate pfree=127 space=8168
qerbiStart first start
qerbiRop: rid=
qerbiCmpSz notfound pctfree=10
qerbiCmpSz adjblksize=7351 length=0
qerbiRop keysize=4 maxbm=3529
kdibcoinit(1104b4d60): srid=
qerbiRop: rid=
kdibcoinit(1104b4888): srid=
qerbiRop: rid=
qerbiRop: rid=
qerbiRop: rid=
kdibcoend(1104b4d60): erid=
qerbiCon: key: (2): c1 02
srid=
kdibcoend(1104b4888): erid=
qerbiCon: key: (2): c1 03
srid=
qerbiFreeMemory: Work heap is used.
从10608的结果我们可以看出来,rowid的下限应该是02 81 05 ac 00 00,encoded bitmap应该分别是c8 0d和c8 12。
到底哪个是对的呢?我们dump一下便知:
BBED> set file 10
FILE# 10
BBED> set block 67725
BLOCK# 67725
BBED> set offset 7986
OFFSET 7986
BBED> dump
File: /iprat02/ipratest/caipratbs_02.DBF (10)
Block: 67725 Offsets: 7986 to 8191 Dba:0x0281088d
------------------------------------------------------------------------
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000
02060281
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 0000e2fd 0601
<32 bytes per line>
从上述dump结果里我们可以看到,oracle实际的物理存储和10608的结果是一致的。
最后我们来说一下怎样来理解encoded bitmap:
键值为1(即c1 02)的bitmap index的encoded bitmap是c8 0d,还原成二进制就是:
11001000 00001101
这个地方要以每个byte为一组,整体是从左往右读,但组内是从右往左读,即翻译过来就是:
00010011 10110000
同理,对于键值为2(即c1 03)的encoded bitmap翻译过来就是
00010011 01001000
大家注意看,后面的一个byte的前5位分别是10110和01001,这不就是ID为1和ID为2的值的分布吗?
SQL> select /*+ full(t1) */* from t1;
ID
----------
1
2
1
1
2
这里encoded bitmap里1表示有,0表示无。
这里oracle的trace文件没有问题,是我错了,稍后我会详细解释一下这个问题。