Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle verwendet oder ignoriert indizierte Spalten je nach Format von to_date(literal)

Ok - ich werde es versuchen, das ist hauptsächlich eine Ableitung von den verfügbaren Informationen:

Warum wählt Oracle einen anderen Ausführungsplan?

In Ihrer zweiten Abfrage mit dem ungewöhnlichen Datumsformat scheint der Optimierer keine Ahnung zu haben, welchen Wert das resultierende Datum hat. Sie sehen das Filterprädikat:

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

Das bedeutet, dass der Optimierer nicht einmal sicher ist, dass das erste Datum kleiner als das zweite ist! Das bedeutet, dass der Optimierer keine Ahnung von der Anzahl der zurückgegebenen Zeilen hat und nur einen generischen Plan verwendet, ohne spezifische Statistiken zu berücksichtigen. Es wäre dasselbe, wenn Sie eine benutzerdefinierte Funktion xyt() hätten, die ein Datum für den Bereich zurückgeben würde. Der Optimierer hat keine Möglichkeit zu wissen, welcher Datumswert sich ergeben wird - Das bedeutet, dass Sie einen allgemeinen Allzweckplan erhalten, der für jeden angegebenen Datumsbereich ziemlich anständig sein sollte.

Im ersten und dritten Fall scheint der Optimierer das Datum direkt zu verstehen und kann anhand von Statistiken die Anzahl der Zeilen erraten, die sich im Datumsbereich befinden. Während die zweite Abfrage an den Optimierer wie BETWEEN X AND 3 lautete Diese Abfrage ist wie BETWEEN 1 AND 3 Also optimiert er den Abfrageplan für die vorhergesagte Anzahl zurückgegebener Zeilen!

Das Seltsame scheint zu sein, dass der Abfrageoptimierer solche Probleme mit einem seltsamen Datumsformat hat, das als Fehler/Verbesserungswunsch eingereicht werden könnte...

Aber ein wichtiger Punkt:

  1. Ein Full Table Scan muss kein SCHLECHTER Plan sein... Außerdem ist die Verwendung eines Indexes nicht immer schneller!
  2. Die Kosten im Abfrageplan stehen in keinem direkten Zusammenhang mit der tatsächlichen Ausführungszeit oder Leistung - es handelt sich um eine interne Messung, um verschiedene Pläne für die GLEICHE ABFRAGE zu vergleichen (Sie können also die Kosten verschiedener Abfragen wie Ihrer Abfragen 1 nicht vergleichen ,2 und 3)

Wenn Sie eine große Anzahl von Zeilen aus einer Tabelle zurückgeben, ist ein vollständiger Tabellenscan ohne Indexzugriff in vielen Fällen viel schneller, insbesondere wenn Sie auf bestimmten Partitionen arbeiten! - Der Tabellenscan greift nur auf die Pertion für den passenden Datumsbereich zu - also nur für das betreffende Datum und gibt alle Zeilen aus dieser Partition zurück. Dies ist viel schneller, als den Index für jede einzelne Zeile abzufragen und dann die Zeile durch Indexzugriff zu extrahieren ... Versuchen Sie, die Abfragen zu profilieren - der vollständige Tabellenscan auf der Partition sollte dreimal so schnell mit viel weniger IO sein