Aggiornamento:
Questo articolo nel mio blog riassume sia la mia risposta che i miei commenti ad altre risposte e mostra i piani di esecuzione effettivi:
SELECT *
FROM a
WHERE a.c IN (SELECT d FROM b)
SELECT a.*
FROM a
JOIN b
ON a.c = b.d
Queste query non sono equivalenti. Possono produrre risultati diversi se la tua tabella b
non è conservata la chiave (cioè i valori di b.d
non sono univoci).
L'equivalente della prima query è il seguente:
SELECT a.*
FROM a
JOIN (
SELECT DISTINCT d
FROM b
) bo
ON a.c = bo.d
Se b.d
è UNIQUE
e contrassegnato come tale (con un UNIQUE INDEX
o UNIQUE CONSTRAINT
), quindi queste query sono identiche e molto probabilmente utilizzeranno piani identici, poiché SQL Server
è abbastanza intelligente da tenerne conto.
SQL Server
può utilizzare uno dei seguenti metodi per eseguire questa query:
-
Se è presente un indice su
a.c
,d
èUNIQUE
eb
è relativamente piccolo rispetto aa
, quindi la condizione viene propagata nella sottoquery e nel sempliceINNER JOIN
viene utilizzato (conb
principale) -
Se è presente un indice su
b.d
ed
non èUNIQUE
, quindi viene propagata anche la condizione eLEFT SEMI JOIN
viene usato. Può essere utilizzato anche per la condizione di cui sopra. -
Se è presente un indice su entrambi
b.d
ea.c
e sono grandi, quindiMERGE SEMI JOIN
viene utilizzato -
Se non è presente alcun indice su nessuna tabella, viene creata una tabella hash su
b
eHASH SEMI JOIN
viene utilizzato.
Nemmeno di questi metodi rivaluta ogni volta l'intera sottoquery.
Vedi questa voce nel mio blog per maggiori dettagli su come funziona:
Ci sono collegamenti per tutti i RDBMS
è dei quattro grandi.