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]
Jeśli wewnętrzna tabela jest poprawnie zindeksowana, podzapytanie w tym miejscu nie jest w ogóle "wykonywane" w ścisłym tego słowa znaczeniu.
Ponieważ podzapytanie jest częścią IN
wyrażenie, warunek jest wypychany do podzapytania i jest przekształcany w EXISTS
.
W rzeczywistości to podzapytanie jest oceniane na każdym kroku:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Możesz to zobaczyć w szczegółowym opisie dostarczonym przez EXPLAIN EXTENDED
.
Dlatego nazywa się to DEPENDENT SUBQUERY
:wynik każdej oceny zależy od wartości table1.id
. Podzapytanie jako takie nie jest skorelowane, jest to zoptymalizowana wersja, która jest skorelowana.
MySQL
zawsze ocenia EXISTS
klauzulę po prostszych filtrach (ponieważ są one znacznie łatwiejsze do oceny i istnieje prawdopodobieństwo, że podzapytanie w ogóle nie zostanie ocenione).
Jeśli chcesz, aby podzapytanie zostało ocenione jednocześnie, przepisz zapytanie w ten sposób:
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]
Wymusza to, aby podzapytanie było wiodące w łączeniu, co jest bardziej wydajne, jeśli podzapytanie jest małe w porównaniu z table_1
i mniej wydajne, jeśli podzapytanie jest duże w porównaniu z table_1
.
Jeśli istnieje indeks w [...].id
użyte w podzapytaniu, podzapytanie zostanie wykonane przy użyciu INDEX FOR GROUP-BY
.