位图索引相对于传统的B*树索引,在叶子节点上采用了完全不同的结构组织方式。传统B*树索引将每一行记录保存为一个叶子节点,上面记录对应的索引列取值和行rowid信息。而位图索引将每个可能的索引取值组织为一个叶子节点。每个位图索引的叶子节点上,记录着该索引键值的起始截止rowid和一个位图向量串。
从本质上将,位图索引通过一个bit位来记录一个数据行是否存在对应键值。这样做对比传统的B*树索引空间节省高。这样与B*树那样直接保存rowid的区别就在于每次都要进行rowid的换算工作。
行级锁是Oracle从问世以来一直引以为豪的重要特性。行级锁的含义就是在进行insert、update和delete等DML操作时,进行锁定的范围都是最小的数据行一级。这样能够保证数据库具有最大程度支持并发的能力。
在使用传统的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实验
当我们进行多个会话同时插入数据时。
//session1:sid=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
从上面我们可以看出,此时发生了阻塞。Session2(sid=148)请求session1(sid=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
//session1(sid=150)
SQL> update t set col='L' where id=3;
1 row updated
//session2(sid=148)
SQL> update t set col='X' where id=4;
(被阻塞!)
SQL> update t set col='X' where id=2;
(被阻塞!)
出现了大量的block现象,而且范围很大。Session1(sid=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
单会话情况下,是不会发生阻塞现象的。
多会话实验
当进行删除的时候,是否会发生同值数据行锁定的情况呢?
//session1(sid=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的不同数据行。
//session2(sid=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。
而对于数据仓库系统DW和OLAP系统,Bitmap Index能发挥出更大的优势。首先是这样的环境下,数据量达到海量级别,对数据检索性能要求高。这样,体积精简、性能优良的Bitmap Index优势明显。更重要的是,这样的系统数据变化DML较少,即使发生也都是大面积的单线程会话导入操作,可以回避Bitmap Index并发缺陷。
对一个对象,要理解优势、劣势和适应环境,才能做到熟练掌握、果断应用。
http://blog.itpub.net/17203031/viewspace-694955