SELECT `table_1`.*
FROM `table_1`
INNER JOIN
`table_2` [...]
INNER JOIN
`table_3` [...]
WHERE `table_1`.`id` IN
(
SELECT `id`
FROM [...]
)
AND [more conditions]
Wenn die innere Tabelle richtig indiziert ist, wird die Unterabfrage hier im strengen Sinne des Wortes überhaupt nicht "ausgeführt".
Da die Unterabfrage Teil eines IN
ist -Ausdruck wird die Bedingung in die Unterabfrage verschoben und in ein EXISTS
umgewandelt .
Tatsächlich wird diese Unterabfrage bei jedem Schritt ausgewertet:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Sie können es tatsächlich in der detaillierten Beschreibung sehen, die von EXPLAIN EXTENDED
bereitgestellt wird .
Deshalb heißt es DEPENDENT SUBQUERY
:Das Ergebnis jeder Auswertung hängt vom Wert von table1.id
ab . Die Unterabfrage als solche ist nicht korreliert, es ist die optimierte Version, die korreliert ist.
MySQL
wertet immer EXISTS
aus -Klausel nach den einfacheren Filtern (da sie viel einfacher auszuwerten sind und die Wahrscheinlichkeit besteht, dass die Unterabfrage überhaupt nicht ausgewertet wird).
Wenn Sie möchten, dass die Unterabfrage auf einmal ausgewertet wird, schreiben Sie die Abfrage wie folgt um:
SELECT table_1.*
FROM (
SELECT DISTINCT id
FROM [...]
) q
JOIN table_1
ON table_1.id = q.id
JOIN table_2
ON [...]
JOIN table_3
ON [...]
WHERE [more conditions]
Dies erzwingt, dass die Unterabfrage im Join führend ist, was effizienter ist, wenn die Unterabfrage im Vergleich zu table_1
klein ist und weniger effizient, wenn die Unterabfrage im Vergleich zu table_1
groß ist .
Wenn es einen Index auf [...].id
gibt in der Unterabfrage verwendet wird, wird die Unterabfrage mit einem INDEX FOR GROUP-BY
durchgeführt .