VIRTUAL INDEX

VIRTUAL INDEX :

A virtual index is a 'fake'index whose definition exists in the data dictionary,
but has no index tress association. It is user by oracle developers to test wheter 
a specific index is going to use useful whthout having to user the disk space 
associated with the realindex. The hidden parameter "_use_nosegment_indexes" is
userd by quest tools and is also used.


SQL> create table  emp as select * from all_objects;
Table created.

SQL> alter table emp add(constraint prim_1 primary key(object_id));
Table altered.

SQL> set autotrace traceonly explain;
SQL> select * from emp where object_id=10;

Execution Plan
----------------------------
Plan hash value: 744524945
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |   158 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |   158 |     2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PRIM_1 |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=10)


If we query the table using a non-indexed column, we see a full table scan:

SQL> set autotrace traceonly explain;
SQL> select * from emp where object_name='USER_TABLES';

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |   316 |    22   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     2 |   316 |    22   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("OBJECT_NAME"='USER_TABLES')

Note
-----
   - dynamic sampling used for this statement (level=2)



If we query the table using a non indexed column,full table scan.
To create the virtual index on this column,simply add the Nosegment clause to the 
create index statement;


SQL> create index vi_ind on emp (object_name) nosegment;
Index created.

If we repeat the previous query we can see the virtual index is not visible to the 
optimizer.

SQL> set autotrace traceonly explain;
SQL> select * from emp where object_name='USER_TABLES';

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |   316 |    22   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     2 |   316 |    22   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("OBJECT_NAME"='USER_TABLES')
To make the virtual index available we must set the _use_nosegment_indexes parameter.

SQL> alter session set "_use_nosegment_indexes"=true;
Session altered.

If we repeat the query we can see that the virtual index is now used.

SQL>  select * from emp where object_name='USER_TABLES';
Execution Plan
----------------------------------------------------------
Plan hash value: 3917735323
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     2 |   316 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     2 |   316 |     5   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | VI_IND |    24 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_NAME"='USER_TABLES')
The virtual index does not appear in the USER_INDEXES view, but it present in the 
USER_OBJECTS view.

SQL> SET AUTOTRACE OFF
SQL> select  index_name from user_indexes;

INDEX_NAME
------------------------------
PRIM_1

SQL> select object_name from user_objects where object_type = 'INDEX';
OBJECT_NAME
--------------------------------------------------------------------------------
PRIM_1
VI_IND

Statistics can be gathered on virtual indexes in the same way as regular indexes, 
but as we have seen previously, there will be no record of this in the USER_INDEXES 
view.

SQL> exec dbms_stats.gather_index_stats(USER,'VI_IND');
PL/SQL procedure successfully completed.
  • June 22, 2018 | 21 views
  • Comments