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]
Ако вътрешната таблица е правилно индексирана, подзаявката тук изобщо не се „изпълнява“ в строгия смисъл на думата.
Тъй като подзаявката е част от IN
израз, условието се вкарва в подзаявката и се трансформира в EXISTS
.
Всъщност тази подзаявка се оценява на всяка стъпка:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Всъщност можете да го видите в подробното описание, предоставено от EXPLAIN EXTENDED
.
Ето защо се нарича DEPENDENT SUBQUERY
:резултатът от всяка оценка зависи от стойността на table1.id
. Подзаявката като такава не е корелирана, а оптимизираната версия е корелирана.
MySQL
винаги оценява EXISTS
клауза след по-простите филтри (тъй като те са много по-лесни за оценка и има вероятност подзаявката изобщо да не бъде оценена).
Ако искате подзаявката да бъде оценена наведнъж, пренапишете заявката по следния начин:
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]
Това принуждава подзаявката да бъде водеща в свързването, което е по-ефективно, ако подзаявката е малка в сравнение с table_1
и по-малко ефективна, ако подзаявката е голяма в сравнение с table_1
.
Ако има индекс на [...].id
използвана в подзаявката, подзаявката ще бъде изпълнена с помощта на INDEX FOR GROUP-BY
.