ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 位图索引(Bitmap Index)——位图索引与数据DML锁定

位图索引(Bitmap Index)——位图索引与数据DML锁定

原创 Linux操作系统 作者:realkid4 时间:2011-05-10 22:36:52 0 删除 编辑

 

位图索引相对于传统的B*树索引,在叶子节点上采用了完全不同的结构组织方式。传统B*树索引将每一行记录保存为一个叶子节点,上面记录对应的索引列取值和行rowid信息。而位图索引将每个可能的索引取值组织为一个叶子节点。每个位图索引的叶子节点上,记录着该索引键值的起始截止rowid和一个位图向量串。

 

 

从本质上将,位图索引通过一个bit位来记录一个数据行是否存在对应键值。这样做对比传统的B*树索引空间节省高。这样与B*树那样直接保存rowid的区别就在于每次都要进行rowid的换算工作。

 

 

行级锁是Oracle从问世以来一直引以为豪的重要特性。行级锁的含义就是在进行insertupdatedeleteDML操作时,进行锁定的范围都是最小的数据行一级。这样能够保证数据库具有最大程度支持并发的能力。

 

 

在使用传统的B*树索引和Bitmap索引之后,这种特性有无变化。是否Bitmap Index具有B*树索引不可比拟的优势呢?下面我们通过增加、修改和删除三个方面的实验来进行说明。

 

 

环境准备

 

SQL> select * from v$version where rownum<2;

 

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Prod

 

SQL> create table t (col varchar2(10));

Table created

 

SQL> create bitmap index idx_t_colbit on t(col);

Index created

 

 

插入实验

 

当向数据表进行数据插入的时候,可以观察到使用位图索引时的锁定现象。下面分别从单会话和多会话两个方面实验。

 

session实验

 

//会话一

SQL> select sid from v$mystat where rownum<2;

       SID

----------

       150

 

SQL> insert into t values ('T');

1 row inserted

 

SQL> commit;

Commit complete

 

 

在事务未提交时,锁状态信息为:

 

SQL> select addr, sid, type, id1,id2, lmode,request,block from v$lock where sid=150;

 

ADDR      SID TYPE        ID1        ID2      LMODE    REQUEST  BLOCK

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

333415A4        150 TM        55439          0          3          0   0

33383BE4        150 TX       262177        867          6          0    0

 

 

此时和一般的行锁没有特殊之处。针对数据表有一个共享锁,对事务存在一个独占锁。

 

 

session实验

 

当我们进行多个会话同时插入数据时。

//session1sid=150

SQL> select * from t;

COL

----------

L

M

T

T

 

SQL> insert into t values ('M');

 

1 row inserted

 

 

此时,session2进行插入操作。

//另起一个会话session2

SQL> select sid from v$mystat where rownum<2;

       SID

----------

       148

 

//插入当前没有的数据值,不会阻塞;

SQL> insert into t values ('X');

1 row inserted

 

//插入当前存在,但是改值没有事务涉及到的数值,不会阻塞;

SQL> insert into t values ('L');

1 row inserted

 

//插入当前正在被修改的值,被阻塞!

SQL> insert into t values ('M');

(会话阻塞!)

 

 

此时,我们检查锁状态信息。

 

 

SQL> select addr, sid, type, id1,id2, lmode,request,block from v$lock where sid=150 or sid=148;

 

ADDR     SID TYPE        ID1        ID2      LMODE    REQUEST    BLOCK

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

33834398         148 TX       327699       1074          0          4   0

333415A4        150 TM        55439          0          3         0   0

33341668        148 TM        55439          0          3          0  0

3337E84C        148 TX       524319       1051          6          0  0

33383BE4        150 TX       327699       1074          6          0  1

 

从上面我们可以看出,此时发生了阻塞。Session2sid=148)请求session1sid=150)独占的事务资源,要求共享(lmode=4)。所以session2被阻塞。

 

在传统的Oracle概念中,insert通常是不会被阻塞的,除非存在主键信息事务内重复的情况。数据表T没有主键,只有可能是由于Bitmap Index的原因造成的锁定,锁定范围是由于session1插入的相同值。

 

结论:在进行insert插入的时候,如果数据列存在位图索引,Oracle会将数据表中当前具有该值的所有行进行锁定。这里行锁机制范围扩大化,一个插入和事务,会影响到多行数据。

 

 

修改操作

 

修改中,我们涉及到将一个索引值修改为另一个索引值的情况。

 

session实验

 

//session1修改操作

SQL> update t set col='M' where col='L';

1 row updated

 

SQL> update t set col='S' where col='M';

2 rows updated

 

SQL> rollback;

Rollback complete

 

 

在单session情况下,进行修改是不会引起阻塞的,因为会话对资源的占有特性。

 

session实验

 

当存在多个会话的时候,就存在出现block的可能。

//添加数据列

SQL> select * from t;

COL                ID

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

M                   1

L                   2

T                   3

T                   4

L                   5

 

//session1sid=150

SQL> update t set col='L' where id=3;

 

1 row updated

 

//session2sid=148

SQL> update t set col='X' where id=4;

(被阻塞!)

 

SQL> update t set col='X' where id=2;

(被阻塞!)

 

 

出现了大量的block现象,而且范围很大。Session1sid=150)只是修改了id=3的数据行,却影响到了原有取值(col=’T’)和新取值(col=’L’)的所有数据行被锁定。

 

结论:在进行update的时候,Bitmap Index带来的锁定范围是很大的。从原有值到新设定的值都会被锁定。

 

 

删除操作

 

单会话实验

 

 

SQL> select * from t;

COL                ID

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

M                   1

L                   2

T                   3

T                   4

L                   5

 

SQL> delete t where id=3;

1 row deleted

 

SQL> delete t where id=4;

1 row deleted

 

SQL> delete t where id=5;

1 row deleted

 

SQL> rollback;

Rollback complete

 

 

单会话情况下,是不会发生阻塞现象的。

 

多会话实验

 

当进行删除的时候,是否会发生同值数据行锁定的情况呢?

//session1sid=150

SQL> select * from t;

COL                ID

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

M                   1

L                   2

T                   3

T                   4

L                   5

 

SQL> delete t where id=4;

1 row deleted

 

 

此时,另一个会话尝试删除相同col的不同数据行。

//session2sid=148

SQL> delete t where id=5;(不同col值的情况,不会阻塞)

1 row deleted

 

SQL> delete t where id=3;(虽然是不同行,但是由于col相同,会被阻塞!)

(会话被阻塞!)

 

 

 

结论:在删除的时候,Oracle会锁定所有删除行对应键值的所有行。

 

 

综合上述的论定,我们可以看到Bitmap Index的一个重要缺陷,就是锁定范围的扩大化。当我们对一个有位图索引的数据表进行DML操作的时候,Oracle会由于Bitmap Index锁定过多的数据行,极端的情况可能会由于一行数据的修改而锁定大部分的数据记录。这种情况在单会话的情况下是允许的,但是一旦是在多会话并发的环境下,进行这样的DML操作就是一场灾难!

 

数据库的一个重要指标就是并行特性,并行特性的好坏决定着系统整体性能。一旦发生这样的阻塞,随之而来就是并行度减少和等待时间增加。这个是大部分OLTP系统不希望看到的。

 

所以,我们也就发现了Bitmap Index适应性的一个重要局限,就是对并发操作支持度差,不适应与OLTP系统。Bitmap Index的容量优势和速率优势,都不足以弥补这方面的劣势。对OLTP系统,我们不要轻易使用Bitmap Index

 

 

而对于数据仓库系统DWOLAP系统,Bitmap Index能发挥出更大的优势。首先是这样的环境下,数据量达到海量级别,对数据检索性能要求高。这样,体积精简、性能优良的Bitmap Index优势明显。更重要的是,这样的系统数据变化DML较少,即使发生也都是大面积的单线程会话导入操作,可以回避Bitmap Index并发缺陷。

 

 

对一个对象,要理解优势、劣势和适应环境,才能做到熟练掌握、果断应用。

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-694955/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7687555