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

JOIN vs. WHERE:Warum weisen zwei Abfragen, die identische Ergebnisse liefern, einen Leistungsunterschied von 3-4 Größenordnungen auf?

MySQL hat bekannte Probleme mit der Optimierung von Abfragen mit korrelierten Unterabfragen oder Unterauswahlen. Bis Version 5.6.5 materialisiert es keine Unterabfragen, es materialisiert jedoch eine abgeleitete Tabelle, die in einem Join verwendet wird.

Im Wesentlichen bedeutet dies, dass, wenn Sie einen Join verwenden, das erste Mal, wenn die Unterabfrage angetroffen wird, MySQL Folgendes ausführt:

SELECT code1 FROM myTable GROUP BY code1 HAVING COUNT(code1) > 1

Und halten Sie die Ergebnisse in einer temporären Tabelle (die gehasht wird, um die Suche zu beschleunigen), dann für jeden Wert in myTable Es wird in der temporären Tabelle nachgesehen, ob der Code vorhanden ist.

Allerdings seit wann Sie IN verwenden Die Unterabfrage wird nicht materialisiert und wie folgt umgeschrieben:

SELECT t1.code1, t1.code2
FROM myTable t1
WHERE EXISTS
    (   SELECT t2.code1 
        FROM myTable t2
        WHERE t2.Code1 = t1.Code1
        GROUP BY t2.code1 
        HAVING COUNT(t2.code1) > 1
    )

Das heißt für jeden code in myTable , wird die Unterabfrage erneut ausgeführt. Wenn Ihre äußere Abfrage sehr eng ist, ist dies in Ordnung, da es effizienter ist, die Unterabfrage nur wenige Male auszuführen, als sie für alle Werte auszuführen und die Ergebnisse in einer temporären Tabelle zu speichern. Wenn Ihre äußere Abfrage jedoch breit ist, führt dies zu Ergebnissen in der inneren Abfrage, die viele Male ausgeführt wird, und hier tritt der Leistungsunterschied ins Spiel.

Anstatt die Unterabfrage ca. 30.000 Mal auszuführen, führen Sie sie also für Ihre Zeilenanzahl einmal aus und suchen dann ca. 30.000 Zeilen in einer temporären Hash-Tabelle mit nur 400 Zeilen nach. Dies würde einen so drastischen Leistungsunterschied erklären.

Dieser Artikel in der Online-Dokumentation erklärt die Optimierung von Unterabfragen viel ausführlicher.