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]
Om den inre tabellen är korrekt indexerad, "utförs" underfrågan här inte alls i en strikt mening av ordet.
Eftersom underfrågan är en del av en IN
uttryck, skjuts villkoret in i underfrågan och det omvandlas till en EXISTS
.
Faktum är att den här underfrågan utvärderas i varje steg:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Du kan faktiskt se det i den detaljerade beskrivningen som tillhandahålls av EXPLAIN EXTENDED
.
Det är därför det kallas DEPENDENT SUBQUERY
:resultatet av varje utvärdering beror på värdet av table1.id
. Underfrågan som sådan är inte korrelerad, det är den optimerade versionen som är korrelerad.
MySQL
utvärderar alltid EXISTS
klausul efter de enklare filtren (eftersom de är mycket lättare att utvärdera och det finns en sannolikhet att underfrågan inte kommer att utvärderas alls).
Om du vill att underfrågan ska utvärderas på en gång, skriv om frågan så här:
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]
Detta tvingar underfrågan att vara ledande i kopplingen, vilket är mer effektivt om underfrågan är liten jämfört med table_1
, och mindre effektiv om underfrågan är stor jämfört med table_1
.
Om det finns ett index på [...].id
används i underfrågan, kommer underfrågan att utföras med en INDEX FOR GROUP-BY
.