Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

IN vs. JOIN mit großen Rowsets

Aktualisierung:

Dieser Artikel in meinem Blog fasst sowohl meine Antwort als auch meine Kommentare zu anderen Antworten zusammen und zeigt tatsächliche Ausführungspläne:

SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

SELECT  a.*
FROM    a
JOIN    b
ON      a.c = b.d

Diese Abfragen sind nicht gleichwertig. Sie können unterschiedliche Ergebnisse liefern, wenn Ihre Tabelle b ist ist kein Schlüssel erhalten (d.h. die Werte von b.d sind nicht eindeutig).

Das Äquivalent der ersten Abfrage lautet wie folgt:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d

Wenn b.d ist UNIQUE und als solche gekennzeichnet (mit einem UNIQUE INDEX). oder UNIQUE CONSTRAINT ), dann sind diese Abfragen identisch und verwenden höchstwahrscheinlich identische Pläne, da SQL Server ist schlau genug, dies zu berücksichtigen.

SQL Server kann eine der folgenden Methoden verwenden, um diese Abfrage auszuführen:

  • Wenn es einen Index auf a.c gibt , d ist UNIQUE und b ist relativ klein im Vergleich zu a , dann wird die Bedingung in die Unterabfrage und den einfachen INNER JOIN propagiert verwendet (mit b führenden)

  • Wenn es einen Index auf b.d gibt und d ist nicht UNIQUE , dann wird auch die Bedingung weitergegeben und LEFT SEMI JOIN wird genutzt. Es kann auch für die oben genannte Bedingung verwendet werden.

  • Wenn es einen Index auf beiden b.d gibt und a.c und sie groß sind, dann MERGE SEMI JOIN verwendet wird

  • Wenn für keine Tabelle ein Index vorhanden ist, wird eine Hash-Tabelle auf b erstellt und HASH SEMI JOIN verwendet wird.

Weder noch dieser Methoden wertet die gesamte Unterabfrage jedes Mal neu aus.

Sehen Sie sich diesen Eintrag in meinem Blog an, um mehr darüber zu erfahren, wie das funktioniert:

Es gibt Links für alle RDBMS 's der großen Vier.