2009-09-03 13 views
6

Ich versuche, eine Abfrage zu optimieren, die so etwas wie dies funktioniert:SQLServer CASE-Ausdrücke - Kurzschlussauswertung?

SELECT 
    ... 
    CASE WHEN (condition) THEN (expensive function call #1) 
    ELSE (expensive function call #2) 
    END 
... 

Der Abfrage-Plan zeigt, dass selbst für den Fall, dass 100% der Zeilen der WHEN-Klausel wird ein wesentlicher Teil der Zeit erfüllt in ausgegeben ruft das Ergebnis in der ELSE-Verzweigung auf. Die einzige Möglichkeit, die ich verstehen kann, besteht darin, davon auszugehen, dass SQLServer beide Ergebnisse auswertet, und dann nur eine basierend auf der Auswertung der WHEN-Bedingung auswählt, aber ich kann keine definitive Referenz finden, ob die Ergebnisse einer CASE-Anweisung werden vor den Bedingungen ausgewertet. Kann mir bitte jemand erklären oder auf eine Referenz verweisen?

+0

Ich kann das überhaupt nicht bestätigen, selbst wenn ich eine teure Funktion versuche, die eine riesige Tabelle abfragt. Wenn ich den ersten Teil des CASE auf 100% true setze, dauert die Abfrage 5 Sekunden. Wenn nicht, ungefähr 10 Minuten. Welche Version von SQL Server? – MartW

Antwort

1

Ist das ein tatsächlicher oder geschätzter Plan? Sql Server erstellt basierend auf den gesammelten Statistiken Pläne basierend auf den gesammelten Statistiken, und das stimmt nicht immer mit den spezifischen Bedingungen überein, die Sie für eine Instanz eines Abfragelaufs senden.

+0

Hoppla, das war's. Wenn die eigentliche Abfrage ausgeführt wird, sieht der Plan völlig anders aus. Tut mir leid, dass ich nicht zuerst daran gedacht habe. –

9

SQL ist eine deklarative Sprache. Sie geben in einer Abfrage das gewünschte Ergebnis an, und der Server kann frei wählen, welche Mittel zur Lieferung dieser Ergebnisse zur Verfügung stehen. Als solche ist die Reihenfolge der Auswertung von SQL-Epxressionen nicht bestimmt und OR und AND Bewertung Kurzschluss nicht auftreten.

jedoch für CASE die Dokumentation besagt eigentlich, dass die order of evaluation occurs in the order of declaration und die Auswertung beendet, nachdem die erste Bedingung erfüllt ist:

  • Wertet input_expression und dann in der angegebenen Reihenfolge, wertet input_expression = when_expression für jeweils WHEN Klausel.

  • Gibt die result_expression des ersten input_expression = when_expression die TRUE zu auswertet.

Das bedeutet, dass, wenn Sie den Ausdruck in dem FALSCH Zweig ausgewertet sehen, Ihre CASE Bedingung falsch ist und wertet manchmal auf FALSE oder UNKNOWN. Stellen Sie sicher, dass die Tri-Values-Logik von SQL berücksichtigt wird (dh, Sie berücksichtigen NULL-Werte). Stellen Sie außerdem sicher, dass die Daten in den Tabellen die erwartete sind (dh die Bedingung wirklich wertet FALSE 100% der Fälle aus).

+0

Nicht ganz. Es gab einen Fehler, der unter Microsoft Connect eingereicht wurde [Aggregate folgen nicht der Semantik von CASE] (https://connect.microsoft.com/SQLServer/feedback/details/691535/), das einen Fall mit der Reihenfolge der Auswertung zeigte der CASE-Ausdrücke wird nicht berücksichtigt. Sogar die [MSDN-Dokumentation] (http://msdn.microsoft.com/en-us/library/ms181765.aspx) wurde aktualisiert: "In einigen Situationen wird ein Ausdruck ausgewertet, bevor eine CASE-Anweisung die Ergebnisse des Ausdrucks empfängt als Eingabe. " – Douglas