在數據庫表數據比較大的時候,我們自然會想到利用index優化來提高性能,當是否真的需要index需要我們考慮。用或者不用,我們可以先通過虛擬索引先來測試一下sql的性能。使用虛擬索引不用故意的去避開業務的高峯期,擔心大表創建索引對系統性能產生影響。
虛擬索引不是物理存在的,它並不會創建實際的索引段,只是在數據字典中加了一個索引的記錄,使得優化器能夠意識到一個索引的存在,從而判斷是否使用該索引作爲訪問路徑。作用僅僅是爲了DBA作SQL優化時使用,DBA根據虛擬索引的優化效果決定是否創建物理索引。
一、虛擬索引的類型
B-TREE索引
BIT位圖索引
在CBO模式下ORACLE優化器會考慮虛擬索引,但是在RBO模式下需要添加hint才行。
二、創建虛擬索引
a、創建一張測試表:
create table test as select * from dba_objects;
b、 創建虛擬索引,首先要將_use_nosegment_indexes的隱含參數設置爲true:
alter session set "_use_nosegment_indexes"=true;
c、虛擬索引的創建語法比較簡單,實際上就是普通索引語法後面加一個nosegment關鍵字:
create index ix_test_id on t(object_id) nosegment;
三、虛擬索引使用
SQl:
select * from t where object_id=1
a、沒有使用索引的執行計劃
SQL> explain plan for select * from test where object_id=1;
Explained
SQL> set linesize 1000
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 2484 | 289 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 12 | 2484 | 289 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
17 rows selected
b、使用虛擬索引的執行計劃
SQL> explain plan for select * from test where object_id=1;
Explained
SQL> set linesize 1000
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2444949661
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 2484 | 5 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 12 | 2484 | 5 (0)|
|* 2 | INDEX RANGE SCAN | IX_TEST_ID | 258 | | 1 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
18 rows selected
從對比可以看出使用虛擬索引可以用來幫助我們優化sql。
四、一些需要注意的地方
a、虛擬索引無法執行alter index選項
b、虛擬索引分析並且有效,但是數據字典裏查不到結果。
c、使用回收站特性的時候,虛擬索引必須顯示drop,才能創建同名的索引。
d、不能創建和虛擬索引同名的實際索引;
e、可以創建和虛擬索引包含相同列但不同名的實際索引;
參考文檔:
http://blog.itpub.net/26015009/viewspace-2080872/
http://www.cnblogs.com/Richardzhu/p/3487594.html