程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> Oracle索引總結(四)- Oracle索引種類之位圖索引,oracle索引

Oracle索引總結(四)- Oracle索引種類之位圖索引,oracle索引

編輯:Oracle教程

Oracle索引總結(四)- Oracle索引種類之位圖索引,oracle索引


位圖索引

1.1 位圖索引概述

  • 位圖索引通過位圖向量,表示索引鍵值在表中的分布。
  • 適用於沒有大量更新操作的對象,如:OLAP數據庫。
  • 對於存在大量更新操作的索引列,不適用位圖索引。因此對於OLTP並不適用。
    • 更新位圖向量時,相應位圖涉及的所有數據行會被鎖定,無法針對這些數據行的該索引列進行DML操作

 

1.2 位圖索引結構的說明

 

與B-tree索引的聯系及區別如下:

  • 與B-tree索引的聯系:位圖索引使用B-tree形式組成。
  • 與B-tree索引的區別:位圖索引的一個索引鍵值對應一個葉子節點。(B-tree的葉節點包含多個索引鍵值)
  • 與B-tree索引的區別:位圖索引使用位圖向量標識鍵值對應的數據行分布情況。(B-tree采用rowid定位數據行)

 

此外:

  • 位圖索引創建時,不需要進行排序,因此速度較快;而B-tree索引創建時,需要排序等操作,因此慢很多。
  • 位圖索引允許鍵值為NULL,因此進行NULL條件查詢時,可以使用索引。而B-tree索引不記錄NULL(組合索引除外),因此會使用全表掃描。
  • 對於表的訪問效率很高
    • 當使用count(XX),可以直接訪問索引就快速得出統計數據.
    • 當根據位圖索引的列進行and,or或 in(x,y,..)查詢時,直接用索引的位圖進行或運算,在訪問數據之前可事先過濾數據.

 

需要重申的是:

  • B樹索引中,由於根據鍵值的rowid定位數據行,因此相同的鍵值存在多次,與相應的rowid對應。
  • 位圖索引中,由於根據位圖向量定位鍵值所在的數據行,因此相同鍵值只需要記錄一次。

 

 

1.3 位圖索引對於執行計劃的影響

對於B-tree索引,CBO優化器會根據數據的具體分布情況,選擇是否應用索引。

對於位圖索引,即使讀取非常大的數據,仍然會選擇索引。

-- 查看測試數據表的結構
Yumiko@sunny >desc test01; Name Null? Type --------------------------------------------- -------- ---------------- OWNER VARCHAR2(30) OBJECT_NAME VARCHAR2(128) SUBOBJECT_NAME VARCHAR2(30) OBJECT_ID NUMBER DATA_OBJECT_ID NUMBER OBJECT_TYPE VARCHAR2(19) CREATED DATE LAST_DDL_TIME DATE TIMESTAMP VARCHAR2(19) STATUS VARCHAR2(7) TEMPORARY VARCHAR2(1) GENERATED VARCHAR2(1) SECONDARY VARCHAR2(1)

-- 查看表的總行數 Yumiko@sunny >select count(*) from test01; COUNT(*) ---------- 22928


-- 查看owner字段的數據分布情況,可以發現owner字段的含SYS的數據非常龐大,存在明顯的數據傾斜
-- 准備為owner字段分兩次,建立b-tree索引以及位圖索引,通過相同的查詢條件,比較索引的使用情況
Yumiko@sunny >select owner,count(*) from test01 group by owner order by count(*); OWNER COUNT(*) ------------------------------ ---------- BI 8 SCOTT 10 SYS 22910

--建立b-tree索引並驗證 Yumiko@sunny >create index BTREE_OWNER on test01(owner); Index created.
Yumiko@sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME from user_indexes where TABLE_NAME = 'TEST01'; INDEX_NAME INDEX_TYPE TABLE_NAME ------------------------------ --------------------------- ------------------------------ BTREE_OWNER NORMAL TEST01
--打開會話根據,已查看執行計劃 Yumiko@sunny >set autotrace trace




--查詢owner字段為BI時,由於從較多數據中檢查個別數據,執行計劃用到了索引掃描,通過索引塊,快速定位目標數據的rowid,進而訪問數據塊獲得結果。此時效率最高
Yumiko@sunny >select * from test01 where owner='BI'; 8 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 725909888 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 1416 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TEST01 | 8 | 1416 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | BTREE_OWNER | 8 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OWNER"='BI') Note ----- - dynamic sampling used for this statement Statistics ---------------------------------------------------------- 40 recursive calls 0 db block gets 84 consistent gets 4 physical reads 0 redo size 2010 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 8 rows processed

-- 查詢owner字段為SYS時,由於數據中該字段的數據存在明顯的數據傾斜,若通過索引方式檢索,將先掃面大部分的索引塊,然後再根據rowid查找數據塊,此時代價十分大,不如直接全表掃描效率高,因此不用索引。
Yumiko@sunny >select * from test01 where owner='SYS'; 22910 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 262542483 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 22064 | 3813K| 159 (2)| 00:00:02 | |* 1 | TABLE ACCESS FULL| TEST01 | 22064 | 3813K| 159 (2)| 00:00:02 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("OWNER"='SYS') Note ----- - dynamic sampling used for this statement Statistics ---------------------------------------------------------- 7 recursive calls 0 db block gets 2288 consistent gets 8 physical reads 0 redo size 1148463 bytes sent via SQL*Net to client 17266 bytes received via SQL*Net from client 1529 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 22910 rows processed

-- 刪除B-tree索引,創建位圖索引並查看 Yumiko@sunny >create bitmap index bitmap_owner on test01(owner); Index created. Yumiko@sunny >select INDEX_NAME,INDEX_TYPE,TABLE_NAME from user_indexes where TABLE_NAME = 'TEST01'; INDEX_NAME INDEX_TYPE TABLE_NAME ------------------------------ --------------------------- ------------------------------ BITMAP_OWNER BITMAP TEST01


-- 打開會話跟蹤,以查看執行計劃 Yumiko@sunny >set autotrace trace





-- 當查看owner為BI時,與b-tree一樣,使用索引掃描的方式進行檢索。 Yumiko@sunny >select * from test01 where owner='BI'; 8 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 3098739824 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 1416 | 55 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | TEST01 | 8 | 1416 | 55 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BITMAP_OWNER | | | | | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("OWNER"='BI') Note ----- - dynamic sampling used for this statement Statistics ---------------------------------------------------------- 40 recursive calls 0 db block gets 82 consistent gets 0 physical reads 0 redo size 2010 bytes sent via SQL*Net to client 469 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 8 rows processed


--當查看owner為SYS時,此時與B樹索引不同,依然選擇了位圖索引
Yumiko@sunny >select * from test01 where owner='SYS'; 22910 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 3098739824 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 22064 | 3813K| 55 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | TEST01 | 22064 | 3813K| 55 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS| | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | BITMAP_OWNER | | | | | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("OWNER"='SYS') Note ----- - dynamic sampling used for this statement Statistics ---------------------------------------------------------- 7 recursive calls 0 db block gets 2130 consistent gets 0 physical reads 0 redo size 2526059 bytes sent via SQL*Net to client 17266 bytes received via SQL*Net from client 1529 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 22910 rows processed

從上面可以看到,對於位圖索引,即使從表中讀取很多行,也會使用索引。

 

 

1.4 DML操作對於位圖索引的影響

對於位圖索引,當一個事務更新一條記錄的索引列鍵值,且未提交事務時,其他事務對於該索引鍵值涉及的數據行的該索引列值的修改,將處於等待。

--查看當前兩個會話的事件,無特殊事件
Yumiko@sunny >select SID,USERNAME,PROGRAM,EVENT from v$session where username='SCOTT'; SID USERNAME PROGRAM EVENT ------- ----------------- ------------------------------------------------------------- 147 SCOTT sqlplus@OA01 (TNS V1-V3) SQL*Net message from client 153 SCOTT sqlplus@OA01 (TNS V1-V3) SQL*Net message from client

--查看表的前三行數據 Yumiko@sunny01 >select OWNER,OBJECT_ID,DATA_OBJECT_ID,OBJECT_TYPE from test01 where rownum < 4; OWNER OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE ------------------------------ ---------- -------------- ------------------- SYS 20 2 TABLE SYS 44 44 INDEX SYS 28 28 TABLE
--發起事務1對於位圖索引列owner為SYS值的一行數據的owner字段的更新操作,但不提交事務。 Yumiko@sunny01 >update test01 set OWNER='SCOTT' where DATA_OBJECT_ID=28; 1 row updated.

--發起事務2對於位圖索引列owner為SYS值的另一行數據庫的owner字段的更新操作,此時事務停頓。 Yumiko@sunny02 >update test01 set OWNER='BI' where DATA_OBJECT_ID=44;

--查看此時會話的事件,發現有row lock等待事件 Yumiko@sunny >select SID,USERNAME,PROGRAM,EVENT from v$session where username='SCOTT'; SID USERNAME PROGRAM EVENT --------- ------------------------------ ------------------------------------------------ 147 SCOTT sqlplus@OA01 (TNS V1-V3) enq: TX - row lock contention 153 SCOTT sqlplus@OA01 (TNS V1-V3) SQL*Net message from client

通過上面的示例證明了對於位圖索引列的更新,相應鍵值的位圖向量涉及的數據行在鍵值更新事務提交前,會始終處於鎖定狀態,其他事務無法對這些數據行的該索引列進行DML操作。

因此,對於DML操作頻繁度較高的OLTP數據庫而言,位圖索引不推薦使用。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved