Frage

Gibt es einen Unterschied in der Leistung der drei folgenden SQL-Anweisungen?

SELECT * FROM tableA WHERE EXISTS (SELECT * FROM tableB WHERE tableA.x = tableB.y)

SELECT * FROM tableA WHERE EXISTS (SELECT y FROM tableB WHERE tableA.x = tableB.y)

SELECT * FROM tableA WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.x = tableB.y)

Sie sollten alle das gleiche Ergebnis Set arbeiten und zurück. Aber ist es gleichgültig, ob die inneren SELECT alle Felder tableB auswählt, ein Feld, oder einfach nur eine Konstante?

Gibt es eine Best Practice, wenn alle Aussagen verhalten gleich?

War es hilfreich?

Lösung

Die Wahrheit über die EXISTS-Klausel ist, dass die SELECT-Klausel nicht in einem EXISTS-Klausel ausgewertet - Sie könnten versuchen:

SELECT * 
  FROM tableA 
 WHERE EXISTS (SELECT 1/0 
                 FROM tableB 
                WHERE tableA.x = tableB.y)

... und sollte eine Division durch Null Fehler erwarten, aber Sie werden nicht, weil es nicht ausgewertet wird. Aus diesem Grunde ist meine Gewohnheit NULL angeben, ist in einer VORHANDEN zeigen, dass die SELECT ignoriert werden kann:

SELECT * 
  FROM tableA 
 WHERE EXISTS (SELECT NULL
                 FROM tableB 
                WHERE tableA.x = tableB.y)

Alles, was zählt in einer Klausel FROM und darüber hinaus Klauseln VORHANDEN ist -. WHERE, GROUP BY, HAVING, etc

Diese Frage wurde nicht mit einer Datenbank im Auge markiert, und es sollte sein, da Verkäufer der Dinge anders handhaben - so zu testen und überprüfen, die erklären / Ausführung bestätigen will. Es ist möglich, dass Verhaltensänderungen zwischen den Versionen ...

Andere Tipps

Auf jeden Fall # 1. Es „sieht“ beängstigend, aber erkennen, das Optimierungsprogramm, das Richtige tun und ist ausdruck Vorsatz. ther ist auch ein leichter Typo Bonus sollte man versehentlich IN vorhanden ist, aber denken geben. # 2 ist akzeptabel, aber nicht ausdrucksstark. Die dritte Option stinkt in meiner nicht ganz so bescheidenen Meinung nach. Es ist zu nah, zu sagen „wenn‚kein Wert‘existiert“ für Komfort.

Generell ist es wichtig, keine Angst zu sein, Code zu schreiben, mearly ineffizient aussieht, wenn es andere Vorteile bietet und eigentlich nicht auf die Leistung auswirken.

Das heißt, der Optimierer fast immer führen Sie Ihre komplizierte Join / select / wizardry Gruppierung ein einfaches speichern VORHANDEN / Unterabfrage auf die gleiche Weise.

Nachdem sich gegeben zu haben ein dickes Lob geschickt Umschreiben, dass böse oder aus einem Sie beitreten wird schließlich erkennen das Optimierungsprogramm verwendete immer noch den gleichen crappy Ausführungsplan der viel leichter zu lösen Abfrage zu verstehen, mit eingebetteten oder auf jeden Fall.

Die Moral der Geschichte ist Ihre Plattformen Optimierer wissen. Probieren Sie verschiedene Dinge und sieht, was tatsächlich getan wird, weil die grassierende Knie Annahmen weichen in Bezug auf ‚dekorativ‘ Query-Optimierung ist fast immer falsch und irrelevant aus meiner Erfahrung.

Ich weiß, dies ist eine alte Post, aber ich dachte es wichtig, Klarheit über hinzuzufügen Warum ein einem Format auf ein anderes wählen könnten.

Zuerst wird, wie andere haben darauf hingewiesen, ist die Datenbank-Engine sollte die Select-Klausel zu ignorieren. Jede Version von SQL Server / tut, Oracle tut, MySQL tut und so weiter. In vielen, viele Monde der Datenbankentwicklung, ich immer nur ein DBMS angetroffen, die nicht ordnungsgemäß die Select-Klausel ignoriert haben: Microsoft Access. Insbesondere ältere Versionen von MS Access (Ich kann nicht auf aktuelle Versionen sprechen).

Vor meiner Entdeckung dieses „Feature“, habe ich Exists( Select *... zu verwenden. Allerdings entdeckte ich, dass MS Access über jede Spalte in der Unterabfrage streamen würde und dann verwerfen sie (Select 1/0 auch nicht funktionieren würde). Das hat mich überzeugt, wechseln Sie zu Select 1. Wenn auch nur ein DBMS dumm war, gibt es eine andere könnte.

Schreiben Exists( Select 1... ist als völlig klar, in der Absicht Förder (Es ist ehrlich gesagt dumm zu behaupten: „Es ist zu nah, zu sagen‚ wenn ‚kein Wert‘ existiert‘für mehr Komfort.“) Und macht die Chancen eines DBMS etwas Dummes mit dem zu tun Select-Anweisung nahezu unmöglich. Select Null würde den gleichen Zweck dienen, sondern ist einfach mehr Zeichen zu schreiben.

wechselte ich Exists( Select 1 absolut sicher zu machen, das DBMS nicht dumm sein könnte. Doch das war vor vielen Monden, und heute würde ich erwarten, dass die meisten Entwickler sehen Exists( Select * erwarten würden, die genau gleich funktioniert.

Das heißt, ich einen guten Grund für die Vermeidung Exists(Select * zur Verfügung stellen kann, auch wenn Ihr DBMS es richtig auswertet. Es ist viel einfacher zu finden und alle Verwendungen von Select * trounce, wenn Sie jede Instanz ihrer Verwendung nicht überspringen müssen in einer Klausel vorhanden ist.

In SQL Server zumindest

Die kleinste Datenmenge, die von der Platte gelesen werden kann, ist eine einzige „Seite“ Festplattenspeicher. Sobald der Prozessor liest ein Datensatz, der die Unterabfrage Prädikate es stoppen kann erfüllt. Die Unterabfrage wird nicht ausgeführt, als ob es wurde auf seine eigene stehen, und enthalten dann in der äußeren Abfrage, wird es als Teil des gesamten Abfrageplan für die ganze Sache ausgeführt. Also, wenn sie als Unterabfrage verwendet, ist es wirklich egal, was in der Select-Klausel ist, wird nichts zurückgegeben“an der äußeren Abfrage sowieso, außer einem boolean, um anzuzeigen, ob ein einzelner Datensatz gefunden wurde oder nicht ...

Alle drei exakt die gleichen Ausführungsplan verwenden

Ich verwende [Select * From ...] immer, wie ich denke, es liest sich besser, indem sie nicht was bedeutet, dass ich etwas Bestimmtes wollen aus der Unterabfrage zurückgegeben.

EDIT: Von dave costa Kommentar ... Oracle auch den gleichen Ausführungsplan für alle drei Optionen verwendet

Dies ist eine der Fragen, die auf die Einleitung eine Art Heiligen Krieg grenzt.

Es ist eine ziemlich gute Diskussion darüber hier .

Ich denke, die Antwort ist wahrscheinlich die dritte Option zu verwenden, aber die Geschwindigkeitserhöhung ist so unendlich, es ist wirklich nicht die Mühe wert. Es ist einfach die Art von Abfrage, die SQL Server intern ohnehin optimieren können, so können Sie feststellen, dass alle Optionen gleichwertig sind.

Die EXISTS gibt ein boolean nicht aktuelle Daten, dass die beste Praxis # 3 zu verwenden ist.

Ausführungsplan . Erfahren Sie es, verwenden Sie es, ich liebe es

Es gibt keine Möglichkeit, wirklich zu erraten.

Zusätzlich zu dem, was andere gesagt haben, die Praxis der Verwendung von SELECT 1 entstand auf altes Microsoft SQL Server (vor 2005) - sein Abfrageoptimierer war nicht klug genug, um physisch fetching Felder aus der Tabelle für SELECT * zu vermeiden. Keine andere DBMS, mein Wissen, hat diesen Mangel.

Die Tests für die Existenz von Zeilen VORHANDEN, nicht das, was in ihnen, so anders als einige Optimierer über ähnlichen Quirk, es ist nicht wirklich wichtig, was in der SELECT-Liste ist.

Die SELECT * scheint gängigste zu sein, aber andere sind auch akzeptabel.

# 3 Sollte das beste sein, wie Sie die zurückgegebenen Daten ohnehin Prinzip muss man. die Felder bringen nur einen zusätzlichen Aufwand hinzufügen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top