web-dev-qa-db-fra.com

Forcer l'utilisation de l'index dans Oracle

J'ai rencontré cette question lors d'une interview et je ne savais pas comment répondre:

Il y a une table qui a un index sur une colonne, et vous interrogez:

select * from table_name where column_having_index="some value";

La requête prend trop de temps et vous découvrez que l'index n'est pas utilisé. Si vous pensez que les performances de la requête seront meilleures en utilisant l'index, comment pourriez-vous forcer la requête à utiliser l'index?

32
Vijay

Vous pouvez utiliser des conseils d'optimisation

select /*+ INDEX(table_name index_name) */ from table etc ...

En savoir plus sur l'utilisation des conseils d'optimisation: http://download.Oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

43
Rene

Il pourrait y avoir plusieurs raisons pour que l'index ne soit pas utilisé. Même après que vous spécifiez des conseils, il y a des chances que l'optimiseur Oracle pense le contraire et décidez de ne pas pour utiliser Index . Vous devez parcourir la partie EXPLAIN PLAN et voir quel est le coût de l'instruction avec INDEX et sans INDEX.

En supposant que Oracle utilise CBO . Le plus souvent, si l'optimiseur pense que le coût est élevé avec INDEX, même si vous le spécifiez dans les conseils, l'optimiseur ignorera et continuera pour l'analyse complète de la table. Votre première action devrait être de vérifier DBA_INDEXES pour savoir quand les statistiques sont LAST_ANALYZED. S'il n'est pas analysé, vous pouvez définir la table, l'index à analyser .

begin 
   DBMS_STATS.GATHER_INDEX_STATS ( OWNNAME=>user
                                 , INDNAME=>IndexName);
end;

Pour table.

begin 
   DBMS_STATS.GATHER_TABLE_STATS ( OWNNAME=>user
                                 , TABNAME=>TableName);
end;

Dans les cas extrêmes, vous pouvez essayer configurer les statistiques par vous-même.

13
Guru

Si vous pensez que les performances de la requête seront meilleures en utilisant l'index, comment pourriez-vous forcer la requête à utiliser l'index?

D'abord, vous vérifieriez bien sûr que l'indice a donné un meilleur résultat pour renvoyer l'ensemble de données complet, non?

L'indice d'index est la clé ici, mais la façon la plus à jour de le spécifier est avec la méthode de dénomination des colonnes plutôt qu'avec la méthode de dénomination des index. Dans votre cas, vous utiliseriez:

select /*+ index(table_name (column_having_index)) */ *
from   table_name
where  column_having_index="some value"; 

Dans des cas plus complexes, vous pourriez ...

select /*+ index(t (t.column_having_index)) */ *
from   my_owner.table_name t,
       ...
where  t.column_having_index="some value"; 

En ce qui concerne les index composites, je ne suis pas sûr que vous ayez besoin de spécifier toutes les colonnes, mais cela semble être une bonne idée. Voir les documents ici http://docs.Oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18 sur plusieurs index_specs et utilisation de index_combine pour plusieurs index, et ici - http://docs.Oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH pour la spécification de plusieurs colonnes dans l'index_spec.

12
David Aldridge

Il existe un index approprié sur column_having_index, et son utilisation augmente en fait les performances, mais Oracle ne l'a pas utilisé ...
Vous devez collecter des statistiques sur votre table pour permettre à l'optimiseur de voir que l'accès aux index peut vous aider. L'utilisation d'un indice direct n'est pas une bonne pratique.

2
Egor Rogov