點陣圖索引(Bitmap Index)——點陣圖索引與資料DML鎖定

realkid4發表於2011-05-10

 

點陣圖索引相對於傳統的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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章