一、引言
DBA在日常維護管理數據庫進行低性能SQL分析時,有時候需要通過創建索引對SQL進行優化,但有些時候我們創建的索引是否能用到?這個只能創建以后才能看出效果,但是在實際工作中,特別是對大表創建索引對系統性能有很大影響,因此我們不得不避開業務高峰時段,但是有沒有一種辦法創建索引而不影響性能呢?有,那就是虛擬索引。
虛擬索引不是物理存在的,它并不會創建實際的索引段,只是在數據字典中加了一個索引的記錄,使得優化器能夠意識到一個索引的存在,從而判斷是否使用該索引作為訪問路徑。作用僅僅是為了DBA作SQL優化時使用,DBA根據虛擬索引的優化效果決定是否創建物理索引。
二、虛擬索引類型
虛擬索引支持B-TREE索引和BIT位圖索引,在CBO模式下ORACLE優化器會考慮虛擬索引,但是在RBO模式下需要添加hint才行。
三、虛擬索引創建實例
SQL> create table scott.t as select * from dba_objects;
Table created.
SQL> alter session set "_use_nosegment_indexes"=true;
Session altered.
SQL> create index scott.ix_t_id on scott.t(object_id) nosegment;
Index created.
SQL> set autot traceonly
SQL> select * from scott.t where object_id=1;
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 206018885
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 2898 | 5 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 14 | 2898 | 5 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IX_T_ID | 330 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
1308 consistent gets
1239 physical reads
0 redo size
1343 bytes sent via SQL*Net to client
512 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
-- 以下看的是真實執行計劃,顯然是用不到索引。
SQL> set autot off
SQL> alter session set statistics_level=all;
Session altered.
SQL> select * from scott.t where object_id=1;
no rows selected
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------
SQL_ID 2qhwh0nzrzx2r, child number 1
-------------------------------------
select * from t where object_id=1
Plan hash value: 1601196873
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.52 | 1242 | 1239 |
|* 1 | TABLE ACCESS FULL| T | 1 | 14 | 0 |00:00:00.52 | 1242 | 1239 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"=1)
Note
-----
- dynamic sampling used for this statement (level=2)
22 rows selected.
-- 從數據字段中是無法找到這個索引的。
SQL> select index_name,status from dba_indexes where table_name='T';
no rows selected
四、虛擬索引的特點
4.1、虛擬索引無法執行alter index選項
SQL> alter index scott.IX_T_ID rebuild;
alter index scott.IX_T_ID rebuild
*
ERROR at line 1:
ORA-08114: can not alter a fake index
4.2、使用回收站特性的時候,虛擬索引必須先drop,才能創建同名的索引。
SQL> drop table scott.t;
Table dropped.
SQL> flashback table scott.t to before drop;
Flashback complete.
SQL> create index scott.idx_t_id on scott.t(object_id) nosegment;
create index scott.idx_t_id on scott.t(object_id) nosegment
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
4.3、不能創建和虛擬索引同名的實際索引;
4.4、可以創建和虛擬索引包含相同列但不同名的實際索引;
4.5、虛擬索引在數據字典里看不到
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。