Mise à jour :
Cet article de mon blog résume à la fois ma réponse et mes commentaires sur d'autres réponses, et montre les plans d'exécution réels :
SELECT *
FROM a
WHERE a.c IN (SELECT d FROM b)
SELECT a.*
FROM a
JOIN b
ON a.c = b.d
Ces requêtes ne sont pas équivalentes. Ils peuvent donner des résultats différents si votre table b
n'est pas la clé conservée (c'est-à-dire les valeurs de b.d
ne sont pas uniques).
L'équivalent de la première requête est le suivant :
SELECT a.*
FROM a
JOIN (
SELECT DISTINCT d
FROM b
) bo
ON a.c = bo.d
Si b.d
est UNIQUE
et marqué comme tel (avec un UNIQUE INDEX
ou UNIQUE CONSTRAINT
), alors ces requêtes sont identiques et utiliseront très probablement des plans identiques, puisque SQL Server
est assez intelligent pour en tenir compte.
SQL Server
peut utiliser l'une des méthodes suivantes pour exécuter cette requête :
-
S'il y a un index sur
a.c
,d
estUNIQUE
etb
est relativement petit par rapport àa
, la condition est propagée dans la sous-requête et le simpleINNER JOIN
est utilisé (avecb
menant) -
S'il y a un index sur
b.d
etd
n'est pasUNIQUE
, alors la condition est également propagée etLEFT SEMI JOIN
est utilisé. Il peut également être utilisé pour la condition ci-dessus. -
S'il y a un index sur les deux
b.d
eta.c
et ils sont grands, alorsMERGE SEMI JOIN
est utilisé -
S'il n'y a pas d'index sur une table, alors une table de hachage est construite sur
b
etHASH SEMI JOIN
est utilisé.
Aucun de ces méthodes réévalue l'ensemble de la sous-requête à chaque fois.
Voir cette entrée dans mon blog pour plus de détails sur la façon dont cela fonctionne :
Il existe des liens pour tous les RDBMS
's des quatre grands.