Dois-je éviter IN () parce que plus lent que EXISTS ()

Dupliquer possible:
Performances SQL Server IN et EXISTS

Dois-je éviter IN () parce que plus lent que EXISTS ()?

SELECT * FROM TABLE1 t1 WHERE EXISTS (SELECT 1 FROM TABLE2 t2 WHERE t1.ID = t2.ID) 

CONTRE

 SELECT * FROM TABLE1 t1 WHERE t1.ID IN(SELECT t2.ID FROM TABLE2 t2) 

De mon enquête, j'ai mis SHOWPLAN_ALL. J'ai le même plan d'exécution et le même coût d'estimation. L'index (pk) est utilisé, chercher sur les deux requêtes. Aucune différence.

Quels sont les autres scénarios ou d'autres cas à faire une grande différence résultat de la requête? L'optimiseur est-il donc l'optimization pour moi d'get le même plan d'exécution?

Ne fais ni Faites ceci:

 SELECT DISTINCT T1.* FROM TABLE1 t1 JOIN TABLE2 t2 ON t1.ID = t2.ID; 

Cela va effectuer tout autre chose par ordre de grandeur.

Les deux requêtes produiront le même plan d'exécution (en supposant qu'aucun index n'a été créé): deux parsings de table et une boucle nestede (join).

La jointure, suggérée par Bohemian, fera un Hash Match à la place de la boucle, ce que j'ai toujours entendu (et voici une preuve: Link ) est le pire type de jointure.

Parmi IN et EXIST (votre question d'actuall), EXISTS a de meilleures performances (prendre un lien à: Link )

Si votre table T2 a beaucoup d'loggings, EXISTS est la meilleure approche, parce que lorsque votre database trouve un logging qui correspond à vos besoins, la condition sera évaluée à vrai et il a arrêté l'parsing de T2. Cependant, dans la clause IN, vous parsingz votre table2 pour chaque ligne de la table1. IN est meilleur que Exists quand vous avez un tas de valeurs, ou peu de valeurs dans la sous-requête. Expandad un peu ma réponse, basée sur Ask Tom réponse: Dans un Select avec dans, par exemple:

 Select * from T1 where x in ( select y from T2 ) 

est habituellement traité comme:

 select * from t1, ( select distinct y from t2 ) t2 where t1.x = t2.y; 

La sous-requête est évaluée, distincte, indexée (ou hachée ou sortingée) et ensuite jointe à la table d'origine (typiquement).

Dans une requête existe comme:

 select * from t1 where exists ( select null from t2 where y = x ) 

Cela est traité plus comme:

 for x in ( select * from t1 ) loop if ( exists ( select null from t2 where y = xx ) then OUTPUT THE RECORD end if end loop 

Il en résulte toujours un balayage complet de T1 alors que la première requête peut utiliser un index sur T1 (x).

Quand est-il approprié et approprié?

  1. Utilisez EXISTS quand … La sous-requête T2 est énorme et prend beaucoup de time et T1 est relativement petit et l'exécution (select null de t2 où y = xx) est très très rapide
  2. Utilisez IN lorsque … Le résultat de la sous-requête est petit – alors IN est généralement plus approprié.
  3. Si la sous-requête et la table externe sont toutes deux énormes, l'une ou l'autre peut fonctionner aussi bien que l'autre dépend des index et d'autres facteurs.