Werden boolesche Ausdrücke in SQL WHERE-Klauseln kurzgeschlossen ?
Beispielsweise:
SELECT *
FROM Table t
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key)
Wenn @key IS NULL als wahr ausgewertet wird, wird @key NICHT NULL UND @key = t.Key ausgewertet?
Wenn nein, warum nicht?
Wenn ja, ist es garantiert? Ist es Teil von ANSI SQL oder datenbankspezifisch?
Wenn datenbankspezifisch, SqlServer? Orakel? MySQL?
sql
short-circuiting
Greg Dean
quelle
quelle
WHERE a = 1 AND b = 2
es für das Datenbankmodul effizient sein könnte, zuerst alle Zeilen mit b = 2 zu finden und dann mit a = 1 zu filtern. Wenn Sie um Garantie bitten, wird das Optimierungsprogramm unbrauchbar.Antworten:
ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf
quelle
CASE
ist kurzgeschlossen.Aus dem oben Gesagten ist ein Kurzschluss nicht wirklich verfügbar.
Wenn Sie es brauchen, schlage ich eine Case-Erklärung vor:
Expr1
wird immer ausgewertet, aber nur einer vonExpr2
undExpr3
wird pro Zeile ausgewertet.quelle
Ich denke, dies ist einer der Fälle, in denen ich es aus drei Gründen so schreiben würde, als würde es nicht kurzschließen.
Denn für MSSQL wird es nicht gelöst, indem man BOL an der offensichtlichen Stelle betrachtet. Für mich ist es daher kanonisch mehrdeutig.
weil ich zumindest dann weiß, dass mein Code funktionieren wird. Und was noch wichtiger ist, auch diejenigen, die nach mir kommen, damit ich sie nicht dazu bringe, sich immer wieder die gleiche Frage zu stellen.
Ich schreibe oft genug für mehrere DBMS-Produkte und möchte mich nicht an die Unterschiede erinnern müssen, wenn ich sie leicht umgehen kann.
quelle
Ich glaube nicht, dass ein Kurzschluss in SQL Server (2005) garantiert ist. SQL Server führt Ihre Abfrage über seinen Optimierungsalgorithmus aus, der viele Faktoren (Indizes, Statistiken, Tabellengröße, Ressourcen usw.) berücksichtigt, um einen effektiven Ausführungsplan zu erstellen. Nach dieser Auswertung können Sie nicht sicher sagen, ob Ihre Kurzschlusslogik garantiert ist.
Ich bin vor einiger Zeit selbst auf dieselbe Frage gestoßen, und meine Forschung hat mir wirklich keine endgültige Antwort gegeben. Sie können eine kleine Abfrage schreiben, um zu beweisen, dass sie funktioniert. Sie können jedoch sicher sein, dass mit zunehmender Auslastung Ihrer Datenbank die Tabellen größer werden und die Dinge in der Datenbank optimiert und geändert werden halt. Ich konnte und habe mich daher nicht auf der Seite der Vorsicht geirrt und CASE in WHERE-Klausel verwendet, um einen Kurzschluss sicherzustellen.
quelle
Sie müssen bedenken, wie Datenbanken funktionieren. Bei einer parametrisierten Abfrage erstellt die Datenbank einen Ausführungsplan basierend auf dieser Abfrage ohne die Werte für die Parameter. Diese Abfrage wird jedes Mal verwendet, wenn die Abfrage ausgeführt wird, unabhängig von den tatsächlich angegebenen Werten. Ob die Abfrage mit bestimmten Werten kurzgeschlossen wird, spielt für den Ausführungsplan keine Rolle.
quelle
Ich benutze dies normalerweise für optionale Parameter. Ist das dasselbe wie ein Kurzschluss?
Dies gibt mir die Möglichkeit, -1 oder was auch immer zu übergeben, um die optionale Überprüfung eines Attributs zu berücksichtigen. Manchmal umfasst dies das Verknüpfen mehrerer Tabellen oder vorzugsweise einer Ansicht.
Sehr praktisch, nicht ganz sicher, welche zusätzliche Arbeit der DB-Motor leistet.
quelle
Für SQL Server hängt es meiner Meinung nach von der Version ab, aber meiner Erfahrung mit SQL Server 2000 wird immer noch @key = t.Key ausgewertet, auch wenn @key null ist. Mit anderen Worten, bei der Bewertung der WHERE-Klausel wird kein effizienter Kurzschluss durchgeführt.
Ich habe Leute gesehen, die eine Struktur wie Ihr Beispiel empfohlen haben, um eine flexible Abfrage durchzuführen, bei der der Benutzer verschiedene Kriterien eingeben oder nicht eingeben kann. Meine Beobachtung ist, dass Key immer noch am Abfrageplan beteiligt ist, wenn @key null ist, und wenn Key indiziert ist, wird der Index nicht effizient verwendet.
Diese Art der flexiblen Abfrage mit unterschiedlichen Kriterien ist wahrscheinlich ein Fall, in dem dynamisch erstelltes SQL wirklich der beste Weg ist. Wenn @key null ist, nehmen Sie es einfach überhaupt nicht in die Abfrage auf.
quelle
Ich bin gerade über diese Frage gestolpert und habe diesen Blogeintrag bereits gefunden: http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/
Dem SQL Server steht es frei, eine Abfrage an einer beliebigen Stelle zu optimieren. In dem im Blogbeitrag angegebenen Beispiel können Sie sich also nicht auf Kurzschlüsse verlassen.
Es ist jedoch anscheinend dokumentiert, dass ein CASE in der schriftlichen Reihenfolge ausgewertet wird - überprüfen Sie die Kommentare dieses Blogposts.
quelle
Das Hauptmerkmal der Kurzschlussbewertung besteht darin, dass die Auswertung des Ausdrucks beendet wird, sobald das Ergebnis bestimmt werden kann. Das bedeutet, dass der Rest des Ausdrucks ignoriert werden kann, da das Ergebnis unabhängig davon, ob es ausgewertet wird oder nicht, dasselbe ist.
Binäre boolesche Operatoren sind komutativ und bedeuten:
Daher gibt es keine Garantie für die Reihenfolge der Bewertung. Die Reihenfolge der Auswertung wird vom Abfrageoptimierer festgelegt.
In Sprachen mit Objekten kann es Situationen geben, in denen Sie boolesche Ausdrücke schreiben können, die nur mit Kurzschlussauswertung ausgewertet werden können. Ihre Beispielcodekonstruktion wird häufig in solchen Sprachen (C #, Delphi, VB) verwendet. Beispielsweise:
Dieses C # -Beispiel verursacht eine Ausnahme, wenn
someString == null
es vollständig ausgewertet wird. Bei der Kurzschlussauswertung funktioniert dies jedes Mal.SQL arbeitet nur mit skalaren Variablen (keine Objekte), die nicht nicht initialisiert werden können. Daher gibt es keine Möglichkeit, boolesche Ausdrücke zu schreiben, die nicht ausgewertet werden können. Wenn Sie einen NULL-Wert haben, gibt jeder Vergleich false zurück.
Das bedeutet, dass Sie in SQL keinen Ausdruck schreiben können, der je nach Verwendung eines Kurzschlusses oder einer vollständigen Auswertung unterschiedlich ausgewertet wird.
Wenn die SQL-Implementierung eine Kurzschlussauswertung verwendet, kann sie die Ausführung von Abfragen hoffentlich nur beschleunigen.
quelle
Ich weiß nichts über Kurzschlüsse, aber ich würde es als Wenn-Sonst-Aussage schreiben
Außerdem sollten sich Variablen immer auf der rechten Seite der Gleichung befinden. das macht es sargable.
http://en.wikipedia.org/wiki/Sargable
quelle
Nachfolgend ein kurzer und schmutziger Test unter SQL Server 2008 R2:
Dies wird sofort ohne Datensätze zurückgegeben. Art von Kurzschlussverhalten war vorhanden.
Dann versuchte dies:
zu wissen, dass keine Aufzeichnung diese Bedingung erfüllen würde:
Dies dauerte einige Sekunden, was darauf hinwies, dass das Kurzschlussverhalten nicht mehr vorhanden war und die komplexe Operation für jeden Datensatz ausgewertet wurde.
Hoffe das hilft Jungs.
quelle
Hier ist eine Demo, um zu beweisen, dass MySQL die WHERE-Klausel kurzschließt :
http://rextester.com/GVE4880
Dadurch werden die folgenden Abfragen ausgeführt:
Der einzige Unterschied zwischen diesen ist die Reihenfolge der Operanden in der ODER-Bedingung.
myslowfunction
Schläft absichtlich eine Sekunde und hat den Nebeneffekt, dass bei jeder Ausführung ein Eintrag zu einer Protokolltabelle hinzugefügt wird. Hier sind die Ergebnisse dessen, was beim Ausführen der beiden oben genannten Abfragen protokolliert wird:Das Obige zeigt, dass eine langsame Funktion mehrmals ausgeführt wird, wenn sie auf der linken Seite einer ODER-Bedingung erscheint, wenn der andere Operand nicht immer wahr ist (aufgrund eines Kurzschlusses).
quelle
Dies dauert im Abfrageanalysator zusätzliche 4 Sekunden, so dass, soweit ich sehen kann, IF nicht einmal kurzgeschlossen ist ...
Es wäre schön, einen garantierten Weg zu haben!
quelle
Es ist jedoch offensichtlich, dass der MS SQL-Server die Kurzschlusstheorie unterstützt, um die Leistung zu verbessern, indem unnötige Überprüfungen vermieden werden.
Unterstützendes Beispiel:
Hier würde das erste Beispiel zu dem Fehler 'Konvertierung fehlgeschlagen, wenn der Varchar-Wert' A 'in den Datentyp int konvertiert wird.'
Während die zweite Bedingung leicht ausgeführt wird, da die Bedingung 1 = 1 als WAHR ausgewertet wird und daher die zweite Bedingung überhaupt nicht ausgeführt wird.
Außerdem
Hier würde die erste Bedingung als falsch ausgewertet, und daher würde das DBMS für die zweite Bedingung gehen, und Sie erhalten erneut den Konvertierungsfehler wie im obigen Beispiel.
HINWEIS: Ich habe den fehlerhaften Zustand nur geschrieben, um zu realisieren, ob der Zustand ausgeführt oder kurzgeschlossen wird, wenn die Abfrageergebnisse in einem Fehler den ausgeführten, anderweitig kurzgeschlossenen Zustand bedeuten.
EINFACHE ERKLÄRUNG
Erwägen,
Da die erste Bedingung auf TRUE ausgewertet wird, ist es bedeutungslos, die zweite Bedingung auszuwerten, da ihre Auswertung in einem beliebigen Wert das Ergebnis überhaupt nicht beeinflussen würde. Daher bietet sich SQL Server eine gute Gelegenheit, Zeit für die Ausführung von Abfragen zu sparen, indem unnötige Bedingungsprüfungen oder Auswertungen übersprungen werden .
Im Fall von "ODER", wenn die erste Bedingung als WAHR bewertet wird, wird die gesamte durch "ODER" verbundene Kette als wahr angesehen, ohne andere zu bewerten.
Wenn die Bedingung1 als wahr ausgewertet wird, ruhen Sie alle Bedingungen aus, bis die Bedingung N übersprungen wird. In verallgemeinerten Wörtern bei der Bestimmung der ersten WAHR würden alle anderen durch ODER verknüpften Bedingungen übersprungen.
Betrachten Sie die zweite Bedingung
Da die erste Bedingung auf FALSE ausgewertet wird, ist es bedeutungslos, die zweite Bedingung auszuwerten, da ihre Auswertung in einem beliebigen Wert das Ergebnis überhaupt nicht beeinflussen würde. Dies ist wiederum eine gute Gelegenheit für SQL Server, Zeit für die Ausführung von Abfragen zu sparen, indem unnötige Bedingungsprüfungen oder Auswertungen übersprungen werden .
Im Fall von "UND", wenn die erste Bedingung als FALSCH bewertet wird, wird die gesamte mit dem "UND" verbundene Kette als als FALSCH bewertet betrachtet, ohne andere zu bewerten.
wenn die condition1 zu ausgewertet wird FALSCH , alle Bedingungen bis ruhen conditionN wäre übersprungenen. In verallgemeinerten Worten bei der Bestimmung von erstem FALSE würden alle anderen durch AND verknüpften Bedingungen übersprungen.
Daher sollte ein weiser Programmierer die Bedingungskette immer so programmieren, dass weniger teure oder am weitesten entfernte Bedingungen zuerst bewertet werden oder der Zustand auf eine Weise angeordnet werden kann, die maximale Kapazität erreichen kann
quelle