本文共 5076 字,大约阅读时间需要 16 分钟。
[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 530SCOTT@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 NSYS@test> select dump('Y',16) from dual ;
DUMP('Y',16)
---------------- Typ=96 Len=1: 59SYS@test> select dump('N',16) from dual ;
DUMP('N',16) ---------------- Typ=96 Len=1: 4eSCOTT@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: 0Itl 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?
--我自己先做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 0xBF00 表示的位图信息就是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 Yalter 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为什么这样设计?
转载地址:http://suqhl.baihongyu.com/