[20150203]关于位图索引2.txt
--许多人知道在oltp系统不适合使用位图索引.它的索引的记录结构如下是:
字段0:键值
字段1:开始rowid
字段2:结束rowid
字段3:位图信息,指示那行记录,位图1=>表示存在.位图0=>表示不存在.
--但是字段4的位图信息,介绍的资料太少,我自己看了链接http://juliandyke.com/Presentations/BitmapIndexInternals.ppt,做一个简单探究.
1.建立测试环境:
SCOTT@test> @ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.3.0 Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
create table t(id number , name varchar2(10), status varchar2(1));
insert into t select rownum-1 id,dbms_random.string('X',10) c20,decode(mod((rownum),64),0,'Y','N') c1 from dual connect by levelcommit ;
create bitmap index ib_t_status on t(status);
SCOTT@test> select owner,segment_name,header_file,header_block from dba_segments where owner=user and segment_name='IB_T_STATUS';
OWNER SEGMENT_NAME HEADER_FILE HEADER_BLOCK
------ -------------------- ----------- ------------
SCOTT IB_T_STATUS 4 530
SCOTT@test> select rowid,t.* from t where rownumROWID ID NAME S
------------------ ---------- -------------------- -
AABI9KAAEAAAACnAAA 0 X9QBZLNSHI N
AABI9KAAEAAAACnAAB 1 QICZ9LZY7G N
AABI9KAAEAAAACnAAC 2 X298VVFOSU N
AABI9KAAEAAAACnAAD 3 OA8VH6YBC2 N
AABI9KAAEAAAACnAAE 4 PHTZFB9VSJ N
SYS@test> select dump('Y',16) from dual ;
DUMP('Y',16)
----------------
Typ=96 Len=1: 59
SYS@test> select dump('N',16) from dual ;
DUMP('N',16)
----------------
Typ=96 Len=1: 4e
SCOTT@test> @lookup_rowid AABI9KAAEAAAACnAAA
OBJECT FILE BLOCK ROW DBA TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
298826 4 167 0 4,167 alter system dump datafile 4 block 167 ;
2.转储一下位图索引结构,我的索引很小,应该仅仅1个根节点.就是在HEADER_BLOCK+1的块地址.
alter system checkpoint ;
alter system dump datafile 4 block 531 ;
Block header dump: 0x01000213
Object id on Block? Y
seg/obj: 0x48f4b csc: 0x02.cb4b6acb itc: 2 flg: E typ: 2 - INDEX
brn: 0 bdba: 0x1000210 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0002.cb4b6acb
Leaf block dump
===============
header address 182927155300=0x2a974ee064
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 7984=0x1f30
kdxcoavs 7944
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[8004] flag: ------, lock: 0, len=28
col 0; len 1; (1): 4e
col 1; len 6; (6): 01 00 00 a7 00 00
col 2; len 6; (6): 01 00 00 a7 00 3f
col 3; len 9; (9): cf ff ff ff ff ff ff ff 7f
row#1[7984] flag: ------, lock: 0, len=20
col 0; len 1; (1): 59
col 1; len 6; (6): 01 00 00 a7 00 38
col 2; len 6; (6): 01 00 00 a7 00 3f
col 3; len 1; (1): 07
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 531 maxblk 531
--其它我不在解析了,主要集中在字段col3(位图信息)上.这里显示07 长度为1.why?
http://juliandyke.com/Presentations/BitmapIndexInternals.ppt
--我自己先做1个总结,位图信息存在一个压缩算法
1.位图信息包含0或者1
2.多个0可以压缩,而1不压缩.
3.位图信息能被分成多组.
4.每个组的第1个字节确定位图信息长度(我觉得包含长度悉信心这样讲也许更准确)???
5.并且根据第1个字节确定是Single-byte group或者Multi-byte group.
小于 大于=192 Multi-byte group 多字节组.
--我们可以看到07 小于192 ,表示单字节组.再具体看Single-Byte Groups:
Single-Byte Groups
1.Byte represents the number of zero bits followed by a one bit
2.Maximum of 191 zero bits
3.Range of byte values is 0x00 to 0xBF
00 表示的位图信息就是1000 0000.
07 表示的位图信息就是0000 0001.
--注意看col1,col2 信息.col1表示开始rowid,col2表示结束rowid.
-- 而开始row从0x38=56,到3f=63,正好对应是id=63,status='Y'.
--换1句话讲,单字节组(假设x)就是表示前面x个0bits,1 bits,后面补齐8位,都是0.
例子 0x00 表示 10000000(二进制) =>可以理解0个0bit,1个bits,剩下补齐8位,也就是7个0.
0x10 表示 00000000 00000000 10000000(二进制) 可以理解16个0bit,1个bits,剩下补齐8位,也就是7个0.
0x12 表示 00000000 00000000 00100000(二进制) 可以理解18个0bit,1个bits,剩下补齐8位,也就是5个0.
--再做一个例子来验证看看
drop table t purge;
create table t(id number , name varchar2(10), status varchar2(1));
insert into t select rownum-1 id,dbms_random.string('X',10) c20,decode(rownum,1,'Y',200,'Y','N') c1 from dual connect by level-- 设置row=0,row=200的记录status='Y'
commit ;
create bitmap index ib_t_status on t(status);
SCOTT@test> select rowid, t.* from t where status='Y';
ROWID ID NAME S
------------------ ---------- -------------------- -
AABI9SAAEAAAACnAAA 0 XWCCYOJDKJ Y
AABI9SAAEAAAACnADH 199 UOYHND35CM Y
alter system checkpoint ;
alter system dump datafile 4 block 531 ;
row#0[7984] flag: ------, lock: 0, len=48
col 0; len 1; (1): 4e
col 1; len 6; (6): 01 00 00 a7 00 00
col 2; len 6; (6): 01 00 00 a7 00 c7
col 3; len 29; (29):
cf fe ff ff ff ff ff ff ff cf ff ff ff ff ff ff ff ff cf ff ff ff ff ff ff
ff ff c8 7f
row#1[7963] flag: ------, lock: 0, len=21
col 0; len 1; (1): 59
col 1; len 6; (6): 01 00 00 a7 00 00
col 2; len 6; (6): 01 00 00 a7 00 c7
col 3; len 2; (2): 00 bf
----- end of leaf block dump -----
End dump data blocks tsn: 4 file#: 4 minblk 531 maxblk 531
--0x c7 = 199
--status='Y',col3 是 00 bf
--这两个数都小于192.也就是单字节组.
00 表示 1000 0000 ,这样就是第1条记录status='Y'.
bf 表示 191个0,1个1,这样前面占8位,这样就是第200条记录status='Y'.
--但愿我把Single-byte group讲解清楚了.真不知道oracle为什么这样设计?