Oracle 位图索引
內容簡介:
1.位圖索引
1.1位圖索引使用注意事項;
1.2?使用位圖索引;
1.3?位圖索引對DML操作的影響;
2.位圖連接索引
2.1?明確需求后使用位圖索引;
2.1創建位圖連接索引的注意事項:
?
1.位圖索引:
1.1位圖索引使用注意事項:
? 一般適用于低基數列;
??適合數據倉庫;
??對于啟用位圖索引的表,應盡量減少或避免DML操作;
??如果對一張含有多列位圖索引的表進行大量DML操作,應考慮將位圖索引刪除,DML操作結束后重建位圖索引;
??不適用于頻繁持續發生DML操作的OLTP系統,會出現行鎖定,阻礙更新性能;
1.2?使用位圖索引
位圖索引與B-TREE索引有很大的不同,一個位圖索引由多個位串組成,每個位串都表示基礎列中一個獨立的有效值;每個位串是打開或關閉,表示該值是否用于某一行;以人員信息表th03?為例,性別(gender)字段的值(男、女、未記錄),假如為其創建位圖索引,那么每個位串(男、女、未記錄)中的單個位表示一個給定行的值是男、女還是未記錄;當判斷某一列是否適合創建位圖索引時,需要考慮是否符合”低基數列”,根據應用程序、數據組成以及數據庫中的表的情況不同,是否創建位圖索引的結論也可能不同;通常用來判斷的一條基本經驗法則是:”如果該列的有效值數目不足表中行數的1%,那么它就適合創建位圖索引,以th03來說,表行數為:500萬行,而性別列的有效值數目僅為3個(?男、女、未記錄),可以確定它適合創建位圖索引:
人員信息表(th03)
?
| 行 | ID | NAME | GENDER | IDCARD | HOMEADDR | JOBNO | BIRTHDATE |
| 1 | 998698 | 李天 | 男 | 440623197007253619 | 水晶洞1 | 526456 | 25-JUL-70 |
| 2 | 998699 | 李花 | 女 | 510802197007251223 | 水晶洞2 | 5785452 | 25-JUL-70 |
| 3 | 584625 | 李某 | 未記錄 | 564551545265642155 | 水晶洞3 | 1565452 | 01-JUL-88 |
?
SQL> create bitmap index ind_th03_gender on th03(gender) tablespace tbs03;
Index created.
Elapsed: 00:00:01.05
SQL> execute dbms_stats.gather_table_stats('sywu','th03',cascade=>true);
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.31
SQL> @/oracle/getind
TABLE_NAME INDEX_NAME COLUMN_NAME? ?SIZE_GB INDEX_TY STATUS COMPRESS NUM_ROWS DISTINCT_KEYS
------------------------------ ------------------------------ ------------------------------ ---------- -------- -------- --------- ---------- -------- ---------- ----
TH03 IND_TH03_GENDER GENDER? ?.001953125?BITMAP VALID DISABLED 453?3
位圖索引的創建非??觳⑶艺加玫目臻g也非常小;位圖索引和B-TREE索引存儲值的方式不同,它存儲表中的每一行值(包括空值),對于B-TREE索引,單列索引不存儲空值,復合索引只要有一個非空值就可以存儲;所以當執行?IS NULL?或者?IS NOT NULL?查詢時位圖索引的效率要高于B-TREE索引:
SQL> select count(*) from th03 where gender is null;
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | BITMAP CONVERSION COUNT | | 1 | 5 | 1 (0)| 00:00:01 |
|* 3 |?BITMAP INDEX SINGLE VALUE|?IND_TH03_GENDER?| | | | |
3 - access("GENDER" IS NULL)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
1 physical reads
如果在相同表相同列建立B-TREE索引,則該執行必須全表掃描:
SQL> select count(*) from th03 where gender is null;
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 14908 (1)| 00:02:59 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 |?TABLE ACCESS FULL|?TH03?| 1 | 5 | 14908 (1)| 00:02:59 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("GENDER" IS NULL)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
54574 consistent gets
54562 physical reads
位圖索引還可以在另外一些情況使用,如使用聚合函數:
SQL> select count(*),count(gender) from th03;
COUNT(*) COUNT(GENDER)
---------- -------------
5000000 5000000
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 203 (0)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | BITMAP CONVERSION TO ROWIDS | | 5000K| 23M| 203 (0)| 00:00:03 |
| 3 |?BITMAP INDEX FAST FULL SCAN|?IND_TH03_GENDER?| | | | |
-------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
232 consistent gets
0 physical reads
如果你決定在應用程序中實現位圖索引,應時不時的檢查建立了位圖索引的列的數據組成,這一點很重要,如果你算錯了包含位圖索引的任何列的基數,可能會對應用程序造成負面影響,如(位圖索引的存儲空間會增加、查詢性能會降低、重建索引的時間將增加);
1.3?位圖索引對DML操作的影響:
為了便于測試,我創建另一張分區表?th04,并為th04的性別、出生日期列創建位圖索引,最后向它插入100萬行數據:
SQL> create table th04
partition by range(id)(
partition th04_part1 values less than(1000000) tablespace tbs03,
partition th04_part2 values less than(2000000) tablespace tbs03,
partition th04_part3 values less than(3000000) tablespace tbs03,
partition th04_part4 values less than(4000000) tablespace tbs03,
partition th04_part5 values less than(5000000) tablespace tbs03,
partition th04_part6 values less than(maxvalue) tablespace tbs03
) as select * from tbbase where 1=0 ;
SQL> create bitmap index ind_th04_gender on th04(gender) local tablespace tbs03;
SQL> create bitmap index ind_th04_birthdate on th04(birthdate) local tablespace tbs03;
SQL>insert into th04 select * from tbbase where rownum<1000001;
1000000 rows created.
Elapsed: 00:00:40.24
從結果可以看出,插入100萬行的數據花費40秒,從表面上看花費的時間似乎是合理的,但當數據量不斷增加時,特別對于一個數據倉庫環境,一天處理幾百萬甚至億行數據是司空見慣的,合理的情況應考慮刪除位圖索引(如果是分區表則將目標分區標記為不可用),執行完DML加載操作后重建位圖索引;
SQL> alter index IND_TH04_GENDER unusable;
SQL> alter index IND_TH04_BIRTHDATE unusable;
SQL> insert into th04 select * from tbbase where rownum<1000001;
禁用位圖索引后,插入100萬行數據只花費23?秒,對于大數據而言這或許可以提高裝載數據的性能;數據裝載結束后重建位圖索引:
SQL> alter index ind_th04_gender rebuild partition TH04_PART1;
alter index ind_th04_gender rebuild partition TH04_PART2;
alter index ind_th04_gender rebuild partition TH04_PART3;
alter index ind_th04_gender rebuild partition TH04_PART4;
alter index ind_th04_gender rebuild partition TH04_PART5;
alter index ind_th04_gender rebuild partition TH04_PART6;
alter index ind_th04_birthdate rebuild partition th04_part1;
.........
重建分區索引也可以通過下面的命令重建:
SQL> alter table th04 modify partition th04_part1 rebuild unusable local indexes;
此命令雖然簡單,但它也有不足之處,對于一個指定的分區,它只能按順序執行;而對于每一個指令發出的命令重建分區,它可以同時執行多個語句,實現并行重建索引;
除裝載數據的影響外,位圖索引也會影響數據的DML操作,請觀察下面的人員信息表數據:
人員信息表(th04)
?
| 行 | ID | NAME | GENDER | IDCARD | HOMEADDR | JOBNO | BIRTHDATE |
| 1 | 998698 | 李天 | 男 | 440623197007253619 | 水晶洞1 | 526456 | 25-JUL-70 |
| 2 | 998699 | 李四 | 男 | 510802197007251223 | 水晶洞2 | 5785452 | 25-JUL-70 |
| ..... | .... | ? | ? | ? | ? | ? | ? |
?
數據顯示他們的出生日期是相同的,并且出生日期列(BIRTHDATE)還建立了位圖索引(?IND_TH04_BIRTHDATE) ,因業務錯誤記錄兩人的出生日期,so,現在對其修改:
---session 1-----
SQL> select distinct sid from v$mystat;
SID
----------
191
SQL> update th04 set birthdate='26-JUL-70' where idcard='440623197007253619';
1 row updated.
此時session 1?的用戶因為業務繁忙沒有及時提交,這時另一個業務員在新的會話?session2中修該另一個錯誤記錄:
----session 2 -----
SQL> select distinct sid from v$mystat;
SID
----------
194
SQL> update th04 set birthdate='27-JUL-70' where idcard='510802197007251223';
session 2?中的用戶會一直處于等待狀態,因為他們修改的錯誤人員出生日期在更新之前在同一個位圖索引位串中,當修改位串中的位信息時位串會被鎖定,直到更新提交后更新位串中的位值;觀察此時的鎖狀態:
SQL>select sid,type,id1,id2,lmode,request,ctime,block from v$lock where sid in(191,194) order by sid
SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- -- ---------- ---------- ---------- ---------- ---------- ----------
191 AE 100 0 4 0 2052 0
191 TM 75667 0 3 0 263 0
191 TX 65562 848 6 0 263 1
191 TM 75668 0 3 0 263 0
191 TO 65927 1 3 0 286 0
194 TM 75668 0 3 0 238 0
194 TX 131081 1071 6 0 238 0
194 TM 75667 0 3 0 238 0
194 TX 65562 848 0 4 238 0
194 AE 100 0 4 0 1406 0
對于session 1(191)此時持有一個6級事務鎖,并且堵塞session 2(194),它們請求的資源是一樣的,這并非巧合;只有當session 1(191)提交或回退后,這個6級事物鎖才會被釋放,session 2(194)才能持有鎖修改數據;
SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
---------- -- ---------- ---------- ---------- ---------- ---------- ----------
191 AE 100 0 4 0 2832 0
191 TO 65927 1 3 0 1066 0
194 TX 131081 1071 6 0 1018 0
194 TM 75667 0 3 0 1018 0
194 TM 75668 0 3 0 1018 0
194 AE 100 0 4 0 2186 0
所以建立位圖索引時,應仔細分析表結構和表數據,作出明智、合理選擇;以上測試因環境、版本、數據庫狀態測試結果可能不同;
?
轉載于:https://www.cnblogs.com/zwl715/p/3855990.html
總結
以上是生活随笔為你收集整理的Oracle 位图索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日置BT3562无法开机怎么办,日常如何
- 下一篇: java源码导入eclipse_spri