Tuning SQL avec des index invisibles

Depuis l’introduction de la version 11gR1, il est possible de créer des index invisibles ou marquer un index existant comme invisible. Un index invisible est un index qui n’est pas utilisé par l’optimizer, donc il ne va pas influencer le plan d’exécution et permettre de tester l’effet de la suppression d’un index sans faire un drop !
Testons donc ces mystérieux index …
Il faut vérifier que le paramètre d’initialisation OPTIMIZER_USE_INVISIBLE_INDEXES  est à FALSE, c’est généralement le cas par default.

SQL> show parameter OPTIMIZER_USE_INVISIBLE_INDEXES;


Créer une table et un index invisible:

SQL> CREATE TABLE DEMO_INVIS_INDEX AS SELECT *  FROM DBA_SOURCE;
SQL> CREATE INDEX T_INVIS ON DEMO_INVIS_INDEX(TYPE) INVISIBLE;


Cet index invisible n’est pas visible pour l’optimizer

SQL> SELECT INDEX_NAME,VISIBILITY FROM USER_INDEXES WHERE  INDEX_NAME = 'T_INVIS';
INDEX_NAME                     VISIBILIT
----------------------------- ---------
T_INVIS                        INVISIBLE


Dans le plan d’exécution ci-dessous, l’index n’est pas pris en compte.

SQL> EXPLAIN PLAN FOR SELECT * FROM DEMO_INVIS_INDEX where TYPE = 'FUNCTION';
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT"
Plan hash value: 2469523831"
--------------------------------------------------------------------------------------
| Id  | Operation         | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                  |   345K|   676M|  5036   (1)| 00:01:01 |
|*  1 |  TABLE ACCESS FULL| DEMO_INVIS_INDEX |   345K|   676M|  5036   (1)| 00:01:01 |
--------------------------------------------------------------------------------------"
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("TYPE"='FUNCTION')


Maintenant si nous changeons l’index de invisible à visible.

SQL> ALTER INDEX T_INVIS VISIBLE;
SQL> SELECT INDEX_NAME,VISIBILITY FROM USER_INDEXES WHERE  INDEX_NAME = 'T_INVIS';
INDEX_NAME             VISIBILIT
------------------------------ ---------
T_INVIS                 VISIBLE

Dans le plan d’exécution ci-dessous, l’index est maintenant bien pris en compte.

SQL>EXPLAIN PLAN FOR SELECT * FROM DEMO_INVIS_INDEX where TYPE = 'FUNCTION';
SQL>SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan  hash value: 341580814
------------------------------------------------------------------------------------------------
| Id  |  Operation                   | Name             | Rows  | Bytes | Cost (%CPU)|  Time     |
------------------------------------------------------------------------------------------------
|   0 |  SELECT STATEMENT            |                  |  1801 |  3617K|    51   (0)|  00:00:01 |
|   1 |   TABLE ACCESS BY INDEX ROWID| DEMO_INVIS_INDEX |  1801 |  3617K|    51   (0)|  00:00:01 |
|*  2 |   INDEX  RANGE SCAN          | T_INVIS          |  1801 |       |     7   (0)| 00:00:01  |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation  id):
---------------------------------------------------
  2 -  access("TYPE"='FUNCTION')