SQL Server Join / Where-Verarbeitungsreihenfolge

18

Nachdem ich Slow SQL-Abfragen gelesen hatte und nicht sicher war, wie ich sie optimieren sollte , dachte ich über die allgemeine Leistung von Abfragen nach. Sicherlich müssen die Ergebnisse der ersten Tabelle (wenn andere Tabellen verknüpft werden) vor dem Verknüpfen so klein wie möglich sein (innere Verknüpfungen für diese Frage), um unsere Abfragen ein bisschen schneller zu machen.

Beispiel, sollte dies:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

Sei besser / schneller als:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

Meine Theorie lautet wie folgt (dies ist möglicherweise nicht die richtige Implementierung, an die ich mich aus einem von mir gelesenen internen SQL Server 2008-Buch (MSFT Press) zu erinnern versuche):

  1. Der Abfrageprozessor erhält zuerst die linke Tabelle (table1)
  2. Verbindet sich mit der zweiten Tabelle (table2) und bildet ein kartesisches Produkt, bevor die erforderlichen Zeilen herausgefiltert werden (falls zutreffend)
  3. Anschließend werden die Klauseln WHERE, ORDER BY, GROUP BY, HAVING mit der letzten SEELCT-Anweisung ausgeführt.

Wenn also in der obigen Anweisung Nr. 1 die Tabelle kleiner ist, muss die SQL-Engine beim Bilden der kartesischen Produkte weniger Arbeit leisten. Wenn Sie dann die where-Anweisung erreichen, haben Sie eine reduzierte Ergebnismenge, aus der Sie im Speicher filtern können.

Ich könnte so weit von der Realität entfernt sein. Wie ich schon sagte, es ist eine Theorie.

Ihre Gedanken?

Hinweis : Ich habe gerade erst über diese Frage nachgedacht und hatte noch keine Gelegenheit, selbst Tests durchzuführen.

Hinweis 2 : Als SQL Server getaggt, da ich nichts über die Implementierung von MySql usw. weiß. Bitte zögern Sie nicht, auf jeden Fall zu antworten / zu kommentieren

Stuart Blackler
quelle

Antworten:

15

Die logische Verarbeitung einer Abfrage erfolgt auf MSDN (geschrieben von Microsoft SQL Server-Team, nicht von Drittanbietern).

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

Darauf folgt eine abgeleitete Tabelle, dann macht die äußere Abfrage es erneut etc etc

Dies ist jedoch logisch : nicht aktuell . Unabhängig davon, wie SQL Server dies tatsächlich tut, wird diese Semantik dem Buchstaben gerecht . Das "Ist" wird vom Query Optimizer (QO) ermittelt und Sie vermeiden das von Ihnen erwähnte Cartesion-Zwischenprodukt.

Es ist erwähnenswert, dass SQL deklarativ ist: Sie sagen "was" nicht "wie" für eine prozedurale / imperative Programmierung (Java, .net). Die Aussage "das passiert davor" ist in vielen Fällen falsch (z. B. Annahme von Kurzschlüssen oder Reihenfolge von L nach R).

In Ihrem obigen Fall generiert der QO den gleichen Plan, unabhängig von seiner Struktur, da es sich um eine einfache Abfrage handelt.

Die QO ist jedoch kostenbasiert und für eine komplexe Abfrage kann es 2 Wochen dauern, bis der ideale Plan erstellt ist. Also macht es "gut genug", was eigentlich nicht ist.

Ihr erster Fall kann dem Optimierer daher helfen, einen besseren Plan zu finden, da die logische Verarbeitungsreihenfolge für die beiden Abfragen unterschiedlich ist. Möglicherweise aber nicht.

Ich habe diesen Trick in SQL Server 2000 verwendet, um die Leistung bei der Berichterstellung von Abfragen um das 60-fache zu verbessern. Da die QO von Version zu Version verbessert wird, können diese Probleme besser gelöst werden.

Und das Buch, das Sie erwähnt haben: Es gibt Streit darüber.
Siehe SO und die nachfolgenden Links: /programming//q/3270338/27535

gbn
quelle
6

Eine SQL-Abfrage ist nicht prozeduraler Natur. Die Verknüpfungsoperatoren werden nicht von oben nach unten verarbeitet. Die Reihenfolge der Tabellen in Ihren Beispielabfragen hat keinen Einfluss auf den Ausführungsplan, da sie logisch äquivalent sind und genau denselben Plan generieren.

Sie haben zwei der Optionen ausgewertet, die das Abfrageoptimierungsprogramm beim Generieren eines Plans für diese Abfrage in Betracht ziehen könnte. Der Hauptfaktor, der die Planauswahl beeinflusst, sind die Statistiken für die beteiligten Tabellen und die Kosten, die mit der Betreiberauswahl in allen Kandidatenplänen verbunden sind.

Ein sehr einfacher Join mit zwei Tabellen wie Ihr Beispiel könnte mit einem von Hunderten verschiedenen Ausführungsplänen zufrieden sein. Der Optimierer entscheidet durch Vergleichen der Kosten dieser Pläne, welche Methode am besten zur Beantwortung Ihrer Anfrage geeignet ist.

Manchmal ist es falsch und Sie können dabei helfen, bessere Entscheidungen zu treffen, indem Sie die Indizierung verbessern, die Statistiken aktualisieren und Hinweise anwenden. In sehr seltenen Fällen möchten Sie möglicherweise die Ausführungsreihenfolge erzwingen, indem Sie den FORCE ORDER-Hinweis verwenden, der jedoch sparsam verwendet werden sollte. Es ist ein Hammer, um eine Nuss zu knacken. Der Optimierer kann normalerweise dazu verwendet werden, bessere Pläne zu generieren, indem er bessere Informationen eingibt.

Mark Storey-Smith
quelle