Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

IN vs. JOIN avec de grands ensembles de lignes

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 est UNIQUE et b est relativement petit par rapport à a , la condition est propagée dans la sous-requête et le simple INNER JOIN est utilisé (avec b menant)

  • S'il y a un index sur b.d et d n'est pas UNIQUE , alors la condition est également propagée et LEFT 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 et a.c et ils sont grands, alors MERGE SEMI JOIN est utilisé

  • S'il n'y a pas d'index sur une table, alors une table de hachage est construite sur b et HASH 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.