it-swarm.com.de

Best Practice zwischen der Verwendung von LEFT JOIN oder NOT EXISTS

Gibt es eine bewährte Methode zwischen der Verwendung eines LEFT JOIN- oder eines NOT EXISTS-Formats?

Was bringt es, wenn man sich gegenseitig nutzt?

Wenn keine, welche sollte bevorzugt werden?

SELECT *
FROM tableA A
LEFT JOIN tableB B
     ON A.idx = B.idx
WHERE B.idx IS NULL

SELECT *
FROM tableA A
WHERE NOT EXISTS
(SELECT idx FROM tableB B WHERE B.idx = A.idx)

Ich verwende Abfragen in Access für eine SQL Server-Datenbank.

72

Der größte Unterschied besteht nicht darin, dass der Join nicht existiert, sondern (wie geschrieben) das SELECT *.

Im ersten Beispiel erhalten Sie alle Spalten von sowohl A als auch B, während Sie im zweiten Beispiel Holen Sie sich nur Spalten von A.

In SQL Server ist die zweite Variante in einem sehr einfachen Beispiel etwas schneller:

Erstellen Sie zwei Beispieltabellen:

CREATE TABLE dbo.A
(
    A_ID INT NOT NULL
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
);

CREATE TABLE dbo.B
(
    B_ID INT NOT NULL
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
);
GO

Fügen Sie 10.000 Zeilen in jede Tabelle ein:

INSERT INTO dbo.A DEFAULT VALUES;
GO 10000

INSERT INTO dbo.B DEFAULT VALUES;
GO 10000

Entfernen Sie jede 5. Zeile aus der zweiten Tabelle:

DELETE 
FROM dbo.B 
WHERE B_ID % 5 = 1;

SELECT COUNT(*) -- shows 10,000
FROM dbo.A;

SELECT COUNT(*) -- shows  8,000
FROM dbo.B;

Führen Sie die beiden Testvarianten SELECT aus:

SELECT *
FROM dbo.A
    LEFT JOIN dbo.B ON A.A_ID = B.B_ID
WHERE B.B_ID IS NULL;

SELECT *
FROM dbo.A
WHERE NOT EXISTS (SELECT 1
    FROM dbo.B
    WHERE b.B_ID = a.A_ID);

Ausführungspläne:

(enter image description here

Die zweite Variante muss die Filteroperation nicht ausführen, da sie den linken Anti-Semi-Join-Operator verwenden kann.

60
Max Vernon

Logischerweise sind sie identisch, aber NOT EXISTS ist näher an dem von Ihnen gewünschten AntiSemiJoin und wird im Allgemeinen bevorzugt. Es wird auch besser hervorgehoben, dass Sie nicht auf die Spalten in B zugreifen können, da sie nur als Filter verwendet werden (im Gegensatz dazu, dass sie mit NULL-Werten verfügbar sind).

Vor vielen Jahren (SQL Server 6.0 ish), LEFT JOIN war schneller, aber das war schon lange nicht mehr der Fall. Heutzutage, NOT EXISTS ist etwas schneller.


Die größte Auswirkung von Access besteht darin, dass die Methode JOIN den Join abschließen muss, bevor sie gefiltert wird, und den verknüpften Satz im Speicher erstellt. Verwenden von NOT EXISTS Es sucht nach der Zeile, weist jedoch keinen Platz für die Spalten zu. Außerdem hört es auf zu suchen, sobald es eine Reihe gefunden hat. Die Leistung von Access variiert etwas stärker, aber eine allgemeine Faustregel lautet: NOT EXISTS neigt dazu, etwas schneller zu sein. Ich würde weniger sagen, dass es sich um "Best Practice" handelt, da mehr Faktoren beteiligt sind.

25
Rob Farley

Eine Ausnahme, die mir aufgefallen ist, dass NOT EXISTS (Jedoch geringfügig) LEFT JOIN ... WHERE IS NULL Überlegen ist, ist die Verwendung von Verbindungsservern .

Aus der Prüfung der Ausführungspläne geht hervor, dass der Operator NOT EXISTS In einer verschachtelten Schleife ausgeführt wird. Wobei es zeilenweise ausgeführt wird (was meiner Meinung nach Sinn macht).

Beispiel für einen Ausführungsplan, der dieses Verhalten demonstriert: enter image description here

7
pimbrouwers

Im Allgemeinen erstellt die Engine einen Ausführungsplan, der im Wesentlichen auf Folgendem basiert:

  1. Die Anzahl der Zeilen in A und B.
  2. Gibt es einen Index für A und/oder B.
  3. Die erwartete Anzahl von Ergebniszeilen (und Zwischenzeilen)
  4. Die Form der Eingabeabfrage (d. H. Ihre Frage)

Für 4):

Der "nicht vorhanden" -Plan empfiehlt einen suchbasierten Plan für Tabelle B. Dies ist eine gute Wahl, wenn Tabelle A klein und Tabelle B groß ist (und ein Index für B vorhanden ist).

Der "Antijoin" -Plan ist eine gute Wahl, wenn Tabelle A sehr groß oder Tabelle B sehr klein oder kein Index für B ist und eine große Ergebnismenge zurückgibt.

Es ist jedoch nur eine "Ermutigung", wie eine gewichtete Eingabe. Ein starkes (1), (2), (3) trifft oft die Wahl für (4) Moot.

(Ignorieren Sie den Effekt, dass Ihr Beispiel aufgrund des von @MaxVernon angesprochenen * unterschiedliche Spalten zurückgibt.).

5
crokusek