Oracle
 sql >> Base de données >  >> RDS >> Oracle

Quelles sont les implications sur les performances d'Oracle IN Clause sans jointure ?

Si les statistiques de votre table sont exactes, il est très peu probable que l'optimiseur choisisse de faire une analyse de table plutôt que d'utiliser l'index de clé primaire lorsque vous n'avez que 1000 éléments codés en dur dans WHERE clause. La meilleure approche serait de collecter (ou de définir) des statistiques précises sur vos objets, car cela devrait entraîner automatiquement de bonnes choses plutôt que d'essayer de faire beaucoup de gymnastique afin de contourner des statistiques incorrectes.

Si nous supposons que les statistiques sont inexactes au point que l'optimiseur serait amené à croire qu'un balayage de table serait plus efficace que l'utilisation de l'index de clé primaire, vous pourriez potentiellement ajouter un DYNAMIC_SAMPLING indice qui obligerait l'optimiseur à collecter des statistiques plus précises avant d'optimiser l'instruction ou une CARDINALITY indice pour remplacer l'estimation de cardinalité par défaut de l'optimiseur. Aucun de ceux-ci ne nécessiterait de connaître quoi que ce soit sur les index disponibles, il faudrait simplement connaître l'alias de la table (ou le nom s'il n'y a pas d'alias). DYNAMIC_SAMPLING serait l'approche la plus sûre et la plus robuste, mais cela ajouterait du temps à l'étape d'analyse.

Si vous créez une instruction SQL avec un nombre variable de paramètres codés en dur dans un IN clause, vous allez probablement vous créer des problèmes de performances en inondant votre pool partagé avec du SQL non partageable et en forçant la base de données à passer beaucoup de temps à analyser chaque variante séparément. Il serait beaucoup plus efficace de créer une seule instruction SQL partageable pouvant être analysée une seule fois. Selon où votre IN les valeurs de la clause proviennent, cela pourrait ressembler à quelque chose comme

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM global_temporary_table);

ou

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM TABLE( nested_table ));

ou

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM some_other_source);

Si vous vous contentez d'une seule instruction SQL partageable, en plus d'éviter le coût d'une réanalyse constante de l'instruction, vous disposez d'un certain nombre d'options pour forcer un plan particulier qui n'implique pas de modifier l'instruction SQL. Différentes versions d'Oracle ont différentes options pour la stabilité du plan -- il y a contours stockés , Gestion du plan SQL , et profils SQL parmi d'autres technologies en fonction de votre version. Vous pouvez les utiliser pour forcer des plans particuliers pour des instructions SQL particulières. Cependant, si vous continuez à générer de nouvelles instructions SQL qui doivent être ré-analysées, il devient très difficile d'utiliser ces technologies.