Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Mysql Exists vs. IN – korrelierte Unterabfrage vs. Unterabfrage?

Dies ist eine RDBMS-agnostische Antwort, kann aber dennoch hilfreich sein. Nach meinem Verständnis ist die korrelierte (auch bekannt als abhängige) Unterabfrage vielleicht der am häufigsten fälschlicherweise für schlechte Leistung beschuldigte Schuldige.

Das Problem (wie es am häufigsten beschrieben wird) besteht darin, dass die innere Abfrage für jede Zeile der äußeren Abfrage verarbeitet wird. Wenn also die äußere Abfrage 1.000 Zeilen und die innere Abfrage 10.000 zurückgibt, muss Ihre Abfrage 10.000.000 Zeilen (äußere × innere) durchlaufen, um ein Ergebnis zu erzielen. Verglichen mit den 11.000 Zeilen (außen + innen) aus einer nicht korrelierten Abfrage über dieselben Ergebnismengen ist das nicht gut.

Dies ist jedoch nur das Worst-Case-Szenario. In vielen Fällen kann das DBMS Indizes ausnutzen, um die Anzahl der Zeilen drastisch zu reduzieren. Selbst wenn nur die innere Abfrage einen Index verwenden kann, werden die 10.000 Zeilen zu ~13 Suchvorgängen, wodurch die Gesamtzahl auf 13.000 sinkt.

Der exists Operator kann die Verarbeitung von Zeilen nach der ersten stoppen, wodurch die Abfragekosten weiter gesenkt werden, insbesondere wenn die meisten äußeren Zeilen mit mindestens einer inneren Zeile übereinstimmen.

In einigen seltenen Fällen habe ich gesehen, dass SQL Server 2008R2 korrelierte Unterabfragen für einen Merge-Join optimiert (der beide Sätze nur einmal durchläuft – bestmögliches Szenario), wobei ein geeigneter Index sowohl in inneren als auch in äußeren Abfragen gefunden werden kann.

Der wahre Schuldige für schlechte Leistung sind nicht unbedingt korrelierte Unterabfragen , aber verschachtelte Scans .