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

Oracle utilise ou ignore la colonne indexée selon le format de to_date(literal)

Ok - je vais essayer, c'est principalement une déduction à partir des informations disponibles :

Pourquoi Oracle choisit-il un plan d'exécution différent ?

Il semble que dans votre deuxième requête avec le format de date inhabituel, l'optimiseur n'ait aucune idée de la valeur de la date résultante. Vous voyez le prédicat de filtre :

1 - filter(TO_DATE('20140610 ','yyyymmdd ')<=TO_DATE(' 2014-06-10 23:59:59', 'syyyy-mm-dd hh24:mi:ss'))

Ce qui signifie que l'optimiseur n'est même pas sûr que la première date soit plus petite que la seconde ! Cela signifie que l'optimiseur n'a aucune idée du nombre de lignes renvoyées et utilisera simplement un plan générique sans tenir compte de statistiques spécifiques. Ce serait la même chose si vous aviez une fonction définie par l'utilisateur xyt() qui renverrait une date pour la plage. L'optimiseur n'a aucun moyen de savoir quelle valeur de date en résultera - Cela signifie que vous obtenez un plan général tout usage, qui devrait être assez correct pour toute plage de dates spécifiée.

Dans le premier et le troisième cas, l'optimiseur semble comprendre directement la date et peut deviner le nombre de lignes comprises dans la plage de dates à l'aide de statistiques. Ainsi, alors que la deuxième requête était adressée à l'optimiseur comme BETWEEN X AND 3 cette requête est du type BETWEEN 1 AND 3 Il optimise donc le plan de requête pour le nombre prévu de lignes renvoyées !

La chose étrange semble être que l'optimiseur de requête a de tels problèmes avec un format de date étrange, pourrait être classé comme un bogue/demande d'amélioration...

Mais un point important :

  1. Une analyse complète de la table ne doit pas nécessairement être un MAUVAIS plan... De plus, l'utilisation d'un index n'est pas toujours plus rapide !
  2. Le coût du plan de requête n'est en aucun cas directement lié au temps d'exécution ou aux performances réels. Il s'agit d'une mesure interne permettant de comparer différents plans pour la MÊME REQUÊTE (vous ne pouvez donc pas comparer le coût de différentes requêtes comme vos requêtes 1 ,2 et 3)

Fondamentalement, si vous renvoyez un grand nombre de lignes d'une table, une analyse complète de la table sans accès à l'index sera dans de nombreux cas beaucoup plus rapide, en particulier lorsque vous travaillez sur certaines partitions ! - L'analyse de table n'accédera qu'à la pertition pour la plage de dates correspondante - donc uniquement pour la date en question et renvoie toutes les lignes de cette partition. C'est beaucoup plus rapide que d'interroger l'index pour chaque ligne, puis d'extraire la ligne par accès à l'index... Essayez de profiler les requêtes - l'analyse complète de la table sur la partition devrait être 3 fois plus rapide avec beaucoup moins d'E/S