暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle位图索引探究实验报告

子衿技术联盟 2016-04-01
362




王涛从事IT行业8年,曾担任高校,食品,银行以及电力能源行业信息系统建设项目经理,技术骨干。专注于系统架构优化,信息系统研发质量管控,软硬件容量测算研究。


1. 实验目的

       研究对oracle数据库位图索引进行DML操作的探究,加深理解位图索引的原理,指导实践中的应用


2. 实验环境

 操作系统平台

Linux MyOracle 2.6.9-78.EL #1 Wed Jul 9 15:27:01  EDT 2008 i686 i686 i386 GNU/Linux

数据库版本

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 –  Prod

实验执行人

王涛

指导人

徐戟,储学荣

创建时间

2014525日星期日 23:43

修改时间

2014527日星期日 18:11


3. 知识准备

      位图索引主要针对大量相同值的列,具体概念就不再索引块的一个索引行中存储键值起止Rowid,以及这些键值的位置编码(位图编码),位置编码中的每一位表示键值对应的数据行的有无。一个块可能指向的是几十甚至成百上千行数据的位置。这种方式存储数据,相对于B*Tree索引,占用的空间非常小,创建和使用非常快。当根据键值查询时,可以根据起始Rowid和位图状态,快速定位数据。

       位图索引的位图在索引块上存储形式:

Leaf block dump

===============

header address 213972084=0xcc0f474

kdxcolev 0

KDXCOLEV Flags = - - -

kdxcolok 0

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 4

kdxcosdc 1

kdxconro2                                       ---表示本索引块上索引位图的数量

kdxcofbo 40=0x28

kdxcofeo 7114=0x1bca

kdxcoavs 7916

kdxlespl 0

kdxlende 0

kdxlenxt 0=0x0

kdxleprv 4254997=0x40ed15

kdxledsz 0

kdxlebksz 8008               ----索引块的大小(8008bytes

/*下面为位图索引的结构,由4个字段组成

row#0[7982] flag: ------, lock: 0,len=26

col 0; len 2; (2):  c1 03                     ---存储位图的键值:2

col 1; len 6; (6):  00 00 00 00 00 00         ---索引rowid的起始地址

col 2; len 6; (6):  00 40 e8 e2 00 0f         ---索引rowid的结束地址

col 3; len 6; (6):  c3 83 b4 d2 bc 01         ---位图信息

row#1[7936] flag: ------, lock: 0, len=26

col 0; len 2; (2):  c1 06

col 1; len 6; (6):  00 0000 00 00 00

col 2; len 6; (6):  00 40ed 76 01 3f

col 3; len 6; (6):  c5 ed87 d9 bc 01

----- end of leaf blockdump -----


4. 实验步骤

4.1位图索引属性验证

4.1.1 准备工作

创建表:CREATE TABLE BM_TMP(CODE CHAR(1));

创建位图索引:CREATE BITMAP INDEX IDX_BM_T ON BM_TMP (CODE);


4.1.2  验证1:每个键值生成一个位图,不同键值生成不同的位图?

具体步骤:

1查找表BM_TMP对应的位图索引IDX_BM_T存储的位置:

SELECTFILE_ID,EXTENT_ID,BLOCK_ID,BLOCKS

FROM DBA_EXTENTS

WHERESEGMENT_NAME='IDX_BM_T';

FILE_ID  EXTENT_ID  BLOCK_ID     BLOCKS

----------     ----------     ----------     ----------

1          0      60809         8


2) 查看索引的存储情况:

alter system dump datafile 1 block 60810;

查看跟踪日志:

Branch block dump

=================

header address 213972036=0xcc0f444

……

kdxconro 1

……

row#0[8049] dba: 4255116=0x40ed8c

col 0; len 1; (1): 2a

col 1; TERM

----- end of branch block dump ----- 


3).插入数据:

  • 插入键值a’:

SQL> insert into bm_tmp values('a');

1 row created.

SQL> commit;

Commit complete. 


SQL> alter system dump datafile 1 block 60810;

System altered.

查看跟踪日志:

Leaf block dump

===============

header address 213972060=0xcc0f45c

……

kdxconro 1

……

row#0[7988] flag: ------, lock: 2, len=25

col 0; len 1; (1):  61                          键值:小写字母aascii

col 1; len 6; (6):  00 0000 00 00 00

col 2; len 6; (6):  00 40ed 82 00 07

col 3; len 6; (6):  c0 a2 90 d9 bc 01              位图信息编码 


  • 插入键值b’:

SQL> insert into bm_tmp values('b');

1 row created.

SQL> commit;

Commit complete. 


SQL> alter system dump datafile 1 block 60810;

System altered.

查看跟踪日志:

Leaf block dump

===============

header address 213972060=0xcc0f45c

……

kdxconro 2

……

row#0[7988] flag: ------, lock: 0, len=25

col 0; len 1; (1):  61                       键值:小写字母aascii

col 1; len 6; (6):  00 00 00 00 00 00

col 2; len 6; (6):  00 40 ed 82 00 07

col 3; len 6; (6):  c0 a2 90 d9 bc 01

row#1[7944] flag: ------, lock: 2, len=25

col 0; len 1; (1):  62                       键值:小写字母bascii

col 1; len 6; (6):  00 00 00 00 00 00

col 2; len 6; (6):  00 40 ed 82 00 07

col 3; len 6; (6):  c1 a2 90 d9 bc 01

----- end of leaf block dump -----

小结:当表中插入ab两个不同键值时会分别生成两个键值对应的位图。

 

4.1.3 验证2:当插入有相同的键值记录会不会重新生成一个新的位图?

  插入键值a之后查看跟踪日志发生变化:

row#0[7918] flag: ------, lock: 2, len=26

col 0; len 1; (1):  61

col 1; len 6; (6):  00 0000 00 00 00

col 2; len 6; (6):  00 40ed 82 00 07

col 3; len 7; (7):  f8 b4 90 d9 bc 0105      ----位图编码被修改(与验证1的结果对比)

row#1[7944] flag: ------, lock: 0, len=25

col 0; len 1; (1):  62

col 1; len 6; (6):  00 0000 00 00 00

col 2; len 6; (6):  00 40ed 82 00 07

col 3; len 6; (6):  c1 a290 d9 bc 01 

小结:当再插入相同键值不会生成新的位图,会在原来的位图上进行修改。


4.1.4  验证3:同一个键值只有一个位图(oracle 10g)?

 将键值为’A’的批量插入表BM_TMP表中

  1. 插入数据27000万数据后查看

BEGIN

FOR i in 1 ..27000 loop

insert into BM_TMP values(‘A');

end loop;

end;

查看跟踪日志:   

row#0[4121] flag: ------,lock: 2, len=3911

col 0; len 1; (1):  41

col 1; len 6; (6):  00 00 00 00 00 00

col 2; len 6; (6):  00 40 ed ba 02 57

col 3; len 3891; (3891):

ff b4 90 d9 bc 01 ff ff ffff ff ff ff ff cf ff ff ff ff ff ff ff ff cf ff

ff ff ff ff ff ff ff cf ffff ff ff ff ff ff ff cf ff ff ff ff ff ff ff ff

cf ff ff ff ff ff ff ff ffcf ff ff ff ff ff ff ff ff cf ff ff ff ff ff ff

……

注:随着键值为A的数据量的增加,相应的位图编码字段不断扩充,当数据插入27000条记录时,编码字段长度已经达3891.


2. 再插入数据500条。

BEGIN

for i in 1 ..500 loop

insert into BM_TMP values(‘A');

end loop;

end;

查看跟踪日志:

kdxconro 2

……

row#0[4084] flag: ------,lock: 2, len=3948

col 0; len 1; (1):  41

col 1; len 6; (6):  00 00 00 00 00 00

col 2; len 6; (6):  00 40 ed bb 00 bf

col 3; len 3928; (3928):

ff b4 90 d9 bc 01 ff ff ffff ff ff ff ff cf ff ff ff ff ff ff ff ff cf ff

ff ff ff ff ff ff ff cf ffff ff ff ff ff ff ff cf ff ff ff ff ff ff ff ff

cf ff ff ff ff ff ff ff ff cfff ff ff ff ff ff ff ff cf ff ff ff ff ff ff

ff ff cf ff ff ff ff ff ffff ff cf

.....

row#1[2916] flag: ------,lock: 2, len=54

col 0; len 1; (1):  41

col 1; len 6; (6):  00 40 ed bb 00 c0

col 2; len 6; (6):  00 40 ed bb 01 b7

col 3; len 35; (35):

cf ff ff ff ff ff ff ff ffcf ff ff ff ff ff ff ff ff cf ff ff ff ff ff ff

ff ff ce ff ff ff ff ff ffff

----- end of leaf block dump -----

注:当再插入500条记录时,发现出现两个有相同键值的位图。

小结:在oracle 10g中,同一键值在位图索引中的位图并非唯一的,主要和位图编码所能承载的记录数有关,通过实验发现随着数据量的增加,位图编码值长度越长,当超过位图编码上限时,就会生成一个新的位图索引(键值和原来位图键值相同)。


4.2位图索引键值修改验证

4.2.1  准备工作

创建表:CREATE TABLE BAP_TAB( ID int,CODE varchar(20));

创建位图索引:CREATE BITMAP INDEX IDX_BM ON BAP_TAB(ID);

数据准备:根据4.1研究的位图属性的特点,将实验数据插入到表BAP_TAB中,具体数据准备步骤(略),结果详见下表:



4.2.2 验证4:同一个索引块,同一位图,修改键值?

会话1SID:149):

SQL> update bap_tab setid=3 where code='b';           ----在索引块60691

1 row updated.

会话2SID:144

SQL> update bap_tab setid=8 where code='C';            ----在索引块60691

现象:会话144处于等待状态.

 

SELECTSID,ID1,TYPE,LMODE,REQUEST,BLOCK

FROM V$LOCK;


       SID        ID1 TY      LMODE   REQUEST      BLOCK

-------------------------------------------------------------------------------------------------

       144     458782 TX          0          4          0

    … …

       167        201 MR          4          0          0

       149     51594 TM          3          0          0

       144     51594 TM          3          0          0

       149     458782 TX          6         0          1

小结:在同一索引块中,同一位图,两个不同会话同时修改键值会出现堵塞现象(锁一组行记录)。


4.2.3  验证5:同一个索引块,不同位图(相同键值),修改相同的键值?

会话1SID:149):

SQL> update bap_tab set id=3 where code='c';      ----在索引块60693

1 row updated.

会话2SID:144

SQL> update bap_tab set id=8 where code='Y';      ----在索引块60693

1 row updated.

现象:两个会话正常执行未出现等待状态。

小结:在同一索引块上,不同位图(相同键值)上两个不同会话同时修改键值时,不会相同堵塞状态,能正常修改键值。


4.2.4  验证6:不同索引块,不同位图(相同键值),修改键值?

会话1SID:149):

SQL> update bap_tab set id=3 where code='c'; ----在索引块60693

1 row updated.

会话2SID:144

SQL> update bap_tab set id=8 where code='b'; ----在索引块60691

1 row updated.

现象:两会话未出现堵塞。

小结:不同索引块上,不同位图(相同键值)的两个不同会话同时修改键值时,不会相同堵塞状态,能正常修改键值。


4.2.5  验证7:将键值修改成相同值?

会话1SID:149):

SQL> update bap_tab set id=4where code='c'; -

1 row updated.

 会话2SID:144

SQL> update bap_tab set id=4where code='b';

现象:会话144处于等待状态.


       SID        ID1 TY      LMODE   REQUEST      BLOCK

       149    262157 TX          0          4          0

… …

       144     262157 TX          6          0          1

… …

小结:两个不同会话将键值修改成相同的值时会出现堵塞现象。


4.2.6  键值修改验证总结

5. 实验结论

经过7个小实验设计验证,我们对oracle 10g的位图索引的工作机制有了一个更清晰的认识,为我们正确应用提供指导依据。

总结:

  • 一个键值会生成一个位图,不同键值会生成不同的位图,即表中有多少种键值,就会成对多少个位图。

  • 当向表中插入有相同的键值的记录时,是不会再重新生成一个新的位图,只会对键值相同的原有位图信息进行修改。

  • 一个位图所能存储索引信息的量是有限,不是无限制存储,当超过上限时,将生成另一个键值相同的位图来存储索引信息(rowid地址与上一个位图地址是连续的)。不过oralce 10g环境中一个位图存储索引信息相比8i9i8条记录来说,算是海量存储。(目前根据实测得在oracle10g上一个位图存储记录数大概是27300多条记录,此数据为估算值仅供参考)。

  • 当两个不同会话将键值修改成相同键值时,会出现堵塞现象。

  • 当对表记录的键值时进行DML操作时,会对索引的位图信息进行修改,并对其加上互斥锁,防止其他会话修改位图,因此,在未提交之前,和此位图相关的一组记录需要修改键值时会处于阻塞状态,无法修改。

总之:出现锁死状态的时候是因为修改的数据刚好在同一位图上,不出现锁死状态是因为不在同一位图上。和索引块,数据块没有直接联系。


联系我们


子衿技术公众号邀请IT界技术大牛激扬文字,发表真知灼见,篇篇干货。

我们依托南瑞集成实验室,开展线下交流,动手实践,欢迎您的加入!

地址:南京市江宁区诚信大道19号南京南瑞集团公司信息系统集成分公司

电话:025-81095705




欢迎扫码关注子衿技术

1)推送在【子衿技术】平台的文章,阅读量超过1000,该文章作者可获赠礼品。

2)投稿数量较多的作者可获赠礼品。

3)从关注的用户中定期抽取3名幸运关注用户,这3名幸运用户可获赠礼品。


 技术干货文章随时欢迎向“子衿技术团队”订阅号投稿。

 投稿邮箱:xx.miaojingwen@163.com



文章转载自子衿技术联盟,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论