Invisible indexes

From Oracle FAQ
⧼orafaq-jumptonavigation⧽⧼orafaq-jumptosearch⧽
Road Works This article may require cleanup to meet OraFAQ's quality standards.
Please improve this article if you can.
Road Works



An invisible index is an alternative to making an index unusable or even to drop it. An invisible index is maintained for any DML operation but is not used by the optimizer unless you explicitly specify the index with a hint. Applications often have to be modified without being able to bring the complete Application offline. Create invisible indexes temporarily for specialized non-standard operations, such as online application upgrades, without affecting the behavior of any existing application. Furthermore, invisible indexes can be used to test the removal of an index without dropping it right away, thus enabling a grace period for testing in production environments.

SQL> create table test
   (sno number(5),name varchar2(20));
Table created.

SQL> create index test_ind on test(sno);

Index created.

SQL> insert into test
    select employee_id,last_name from employees;

107 rows created.

SQL> commit;

Commit complete.

Above, we created a table called TEST, we inserted some data into TEST, and we created a INDEX on the SNO column.

SQL> select index_name,column_name from user_ind_columns
    where table_name='TEST';

INDEX_NAME                     COLUMN_NAME
------------------------------ ------------------------------
TEST_IND                       SNO

Here we checked our indexed column by user_ind_columns.

We are now going to check how the query will process by the oracle server.

SQL> explain plan for
    select * from test where sno in (106,135,200);

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------
Plan hash value: 519842909

-----------------------------------------------------------------------------------------
| Id  | Operation                    | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |          |     3 |    75 |     2   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR             |          |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST     |     3 |    75 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | TEST_IND |     1 |       |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Here you can notice that the query is using INDEX RANGE SCAN on TEST_IND index.

SQL> desc user_indexes
Name                                                  Null?    Type
----------------------------------------------------- -------- ---------------
--------------------
INDEX_NAME                                            NOT NULL VARCHAR2(30)
...
VISIBILITY                                                     VARCHAR2(9)        <<<<NEW IN 11G
...

SQL> select index_name,visibility from user_indexes
    where table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
TEST_IND                       VISIBLE

SQL> alter index test_ind invisible;     <<<<<<< I want to invisible mine index.

Index altered.

Now we can check our index status from user_indexes which have new column VISIBILITY

SQL> select index_name,visibility from user_indexes
    where table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
TEST_IND                       INVISIBLE

you can see that index is invisible now its means oracle can't see it now.

now we again check the same explain plan for same query and compare the results.

SQL> explain plan for
  2  select * from test where sno in (106,135,200);

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------
Plan hash value: 1357081020

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     3 |    75 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST |     3 |    75 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

now in above explain plan you can see oracle didn't use the index as it used in previous query.

SQL> select index_name,visibility from user_indexes
    where table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
TEST_IND                       INVISIBLE

SQL> alter index test_ind visible;

Index altered.

SQL> select index_name,visibility from user_indexes
    where table_name='TEST';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
TEST_IND                       VISIBLE