2009-01-27 4 views
22

In Sql Server 2005, wenn ich mehrere Parameter habe ich die Garantie, dass der Evaluierungsauftrag immer von links nach rechts sein?Wählen Sie "where clause" Bewertungsreihenfolge

Anhand eines Beispiels:

select a from table where c=1 and d=2

In dieser Abfrage, wenn die "c = 1" Zustand der Zustand "d = 2" nicht wird nie ausgewertet werden?

PS- „c“ eine ganze Zahl indizierte Spalte, ist d eine große varchar und nicht lösbaren Spalte, die

Update einen vollständigen Tabellenscan erfordert ich habe versucht, zwei Abfragen oder bedingte Anweisungen zu vermeiden Durchführung I Ich brauche nur etwas wie: Wenn "c condition" fehlschlägt, gibt es eine Möglichkeit, die schwere "d-Bedingung" zu vermeiden, da sie in meinem Fall nicht benötigt wird.

Antwort

26

Es gibt keine Garantien für die Evaluierungsreihenfolge. Der Optimierer versucht mithilfe der verfügbaren Informationen die effizienteste Methode zum Ausführen der Abfrage zu finden.

In diesem Fall sollte der Optimierer in den Index schauen, um alle Zeilen zu finden, die mit dem Prädikat auf c übereinstimmen, und dann diese Zeilen aus den Tabellendaten abrufen, um das Prädikat für d zu ermitteln .

Wenn jedoch festgestellt wird, dass der Index für c nicht sehr selektiv ist (obwohl in Ihrem Beispiel eine Gender-Spalte selten sinnvoll indexiert wird), kann sie dennoch den Tabellen-Scan durchführen.

Um die Ausführungsreihenfolge zu bestimmen, sollten Sie einen EXPLAIN-Plan für Ihre Abfrage erhalten. Beachten Sie jedoch, dass sich dieser Plan je nachdem ändern kann, was der Optimierer gerade für die beste Abfrage hält.

+0

Obwohl nicht explizit in meiner Frage die "Suche nicht indizierte Spalte unter den gefundenen Elementen in der indizierten Spalte" Problem war auch in meinen Gedanken. In meinem Fall entspricht es meinen Bedürfnissen völlig, weil das Abfragen der indizierten Spalte zuerst nur eine kleine Menge von zu filternden Datensätzen lässt, was kein Problem ist. – t3mujin

+1

Denken Sie nur an meinen letzten Satz: Der Optimierer kann für jede Ausführung einen anderen Abfrageplan wählen . Es gibt Möglichkeiten, Pläne zu "pinnen" und auch Hinweise zum Optimierer anzugeben; Ich weiß nicht, wie diese in MS-SQL funktionieren. – kdgregory

+1

Der Sinn der Verwendung einer deklarativen Sprache besteht darin, dass das System den besten Ausführungsplan für Sie ermittelt.Optimierer tendieren dazu, mit den aktuellen Statistiken in Ordnung zu kommen; etwas, das "eddies" genannt wird, kann theoretisch ohne Statistiken funktionieren - aber sie sind eine neuere Erfindung und möglicherweise nicht in MS-SQL. – SquareCog

4

SQL Server generiert für jede ausgeführte Anweisung einen optimierten Plan. Sie müssen Ihre WHERE-Klausel nicht bestellen, um diesen Vorteil zu erhalten. Die einzige garuntee Sie haben, ist, dass es Anweisungen, um läuft so:

SELECT A FROM B WHERE C 
SELECT D FROM E WHERE F 

wird die erste Zeile vor dem zweiten Lauf.

+1

Mit anderen Worten: NEIN. SQL Server wird die Bedingungen neu ordnen, in denen es am schnellsten ist. Wenn Ihre Bedingungen Nebenwirkungen haben (vielleicht über UDF-Funktionsaufrufe), könnte dies zu Problemen führen. –

+2

Das Einfügen von UDFs in WHERE-Klauseln kann katastrophal langsam sein. Wir mussten mehr oder weniger verbieten, dass die Aufführung so schlecht war. – Joe

+0

Das ist nicht ganz richtig. –

2

Sie können sich den Ausführungsplan der Abfrage ansehen und feststellen, was sie eigentlich zu tun versucht. Ich denke, die Abfrage-Engine von SQL Server sollte diese Art von Scan durchführen und sie intelligent in Operationen übersetzen. Zum Beispiel, wenn Sie "teur-op AND false" tun, wird es schnell zu false ausgewertet.

Aus was ich gelernt habe, was Sie tippen, ist (und kann) anders als das, was tatsächlich ausgeführt wird. Sie sagen dem Server lediglich, welche Art von Ergebnissen Sie erwarten. Wie es zu der Antwort kommt, korreliert nicht von links nach rechts des von Ihnen bereitgestellten Codes.

1

Eine Möglichkeit, die Bewertungsreihenfolge zu steuern, ist der CASE-Ausdruck.

[Bearbeiten]

Die populäre Meinung, die ich zum Ausdruck bringen wollte war:

Sie nicht auf die Expression Auswerteauftrag für Dinge wie „WHERE OR“, da der Optimierer einen Plan könnte wählen abhängen , die das zweite Prädikat vor dem ersten Prädikat auswertet. Aber Reihenfolge der Auswertung der Ausdrücke in einer CASE-Anweisung ist fest, so können Sie sich auf deterministische Kurzschlussauswertung einer CASE Anweisung verlassen.

Es geht ein bisschen komplizierter als das, wie in der Website unten erklärt:

http://blogs.msdn.com/b/bartd/archive/2011/03/03/don-t-depend-on-expression-short-circuiting-in-t-sql-not-even-with-case.aspx

+1

Die verlinkte Seite wurde entfernt. – Conrad

+1

Danke @Conrad, aktualisiert die Antwort etwas –

2

Wenn Sie sicher sein wollen, können Sie die Query Execution Plan überprüfen. Der Ausführungsplan, den MSSQL erstellt/optimiert, ist intelligent genug, um die indizierte Spalte vor einer varchar-Spalte zu überprüfen.

+1

Können wir uns auf diese Informationen 100% verlassen? –

1

Der MS SQL Server-Abfrageoptimierer hat einen Kurzschluss, ja. Garantiert.

Run this:

select 1 where 1 = 0 and 1/0 = 10 

Es wird gut laufen und nicht einmal Fehler, obwohl Sie durch Null sind Dividieren, da der Abfrageoptimierer Kurzschluss die where-Klausel zu bewerten. Dies hat Auswirkungen auf jede where-Klausel, in der Sie "and" -ing sind und eine der beiden Teile eine Konstante ist.

+1

Entschuldigung, ich glaube nicht, dass Sie Recht haben. Ich denke, @kdgregory ist richtig, denn hier gibt es keine Garantie. Der Abfrageoptimierer entscheidet, was am besten ist. –

+0

Es ist definitiv nicht garantiert - ich habe gerade eine Situation, in der ich einen Kurzschluss haben möchte, um die Auswertung von Ausdrücken zu vermeiden, wenn der Wahrheitswert bereits bekannt ist (nach der üblichen Operatorpriorität), aber das passiert nicht. – Conrad

+0

Diese beiden Teile der where-Klausel sind triviale Ausdrücke, sodass der Abfrageoptimierer sie nicht neu anordnen muss. Versuchen Sie diese stattdessen: Wählen Sie 1, wo vorhanden ist (wählen Sie "beliebige Zeilen?" Aus dbo.LargishTable) und 1/0 = 10 Es gibt einige Schwellenwerte basierend auf der Art, wie der Abfrageoptimierer Ausführungspläne generiert, die die Evaluierungsreihenfolge bestimmen . – Davos

1

Kurzschluss ist erfolgt, wenn die Bedingung, auf die wir verweisen, nur Literale oder Konstanten enthält. Nehmen wir zum Beispiel an, wir hätten eine Tabelle TableA, die eine Spaltennummer mit allen positiven Zahlen von 1 bis 10 hat, und dann, wenn ich diese Abfrage schreibe.

Wählen num aus TableA WHERE TableA.num < 0 und 1/0 = 10.

Es in Fehler.

Ist Compiler schlau genug, um zu bestimmen, dass meine zweite Klausel besteht aus Konstanten, so sollte es vor Auswertung der Klausel auswerten, die einen Scan von Tabelle oder Index erfordert?