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]
Als de binnentabel correct is geïndexeerd, wordt de subquery hier helemaal niet "uitgevoerd" in de strikte zin van het woord.
Aangezien de subquery deel uitmaakt van een IN
expressie, wordt de voorwaarde in de subquery geduwd en wordt deze omgezet in een EXISTS
.
In feite wordt deze subquery bij elke stap geëvalueerd:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Je kunt het echt zien in de gedetailleerde beschrijving van EXPLAIN EXTENDED
.
Daarom heet het DEPENDENT SUBQUERY
:het resultaat van elke evaluatie hangt af van de waarde van table1.id
. De subquery als zodanig is niet gecorreleerd, het is de geoptimaliseerde versie die is gecorreleerd.
MySQL
evalueert altijd de EXISTS
clausule na de meer eenvoudige filters (omdat ze veel gemakkelijker te evalueren zijn en de kans bestaat dat de subquery helemaal niet wordt geëvalueerd).
Als u wilt dat de subquery in één keer wordt geëvalueerd, herschrijft u de query als volgt:
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]
Dit dwingt de subquery leidend te zijn in de join, wat efficiënter is als de subquery klein is in vergelijking met table_1
, en minder efficiënt als de subquery groot is in vergelijking met table_1
.
Als er een index is op [...].id
gebruikt in de subquery, wordt de subquery uitgevoerd met een INDEX FOR GROUP-BY
.