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]
Se la tabella interna è indicizzata correttamente, la sottoquery qui non viene "eseguita" in senso stretto.
Poiché la sottoquery fa parte di un IN
espressione, la condizione viene inserita nella sottoquery e viene trasformata in un EXISTS
.
In effetti, questa sottoquery viene valutata ad ogni passaggio:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Puoi effettivamente vederlo nella descrizione dettagliata fornita da EXPLAIN EXTENDED
.
Ecco perché si chiama DEPENDENT SUBQUERY
:il risultato di ogni valutazione dipende dal valore di table1.id
. La sottoquery in quanto tale non è correlata, è la versione ottimizzata che è correlata.
MySQL
valuta sempre EXISTS
clausola dopo i filtri più semplici (poiché sono molto più facili da valutare e c'è la probabilità che la sottoquery non venga valutata affatto).
Se vuoi che la sottoquery venga valutata tutta in una volta, riscrivi la query come segue:
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]
Ciò costringe la sottoquery a condurre il join, il che è più efficiente se la sottoquery è piccola rispetto a table_1
e meno efficiente se la sottoquery è grande rispetto a table_1
.
Se è presente un indice su [...].id
utilizzato nella sottoquery, la sottoquery verrà eseguita utilizzando un INDEX FOR GROUP-BY
.