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
.
Проблема с нажатием подзапроса вниз заключается в том, что это невозможно, если подзапрос зависит от постоянной части внешнего запроса (см. Https://stackoverflow.com/questions/44859809/how-to-optimize-dependent-subquery -with-constant-expression) – andig