web-dev-qa-db-fra.com

Performances entre SQL Server IN et EXISTS

Je suis curieux de savoir lequel des éléments ci-dessous serait plus efficace?

J'ai toujours été un peu prudent quant à l'utilisation de IN car je pense que SQL Server transforme le jeu de résultats en une grosse instruction IF. Cela pourrait entraîner de mauvaises performances pour un grand nombre de résultats. Pour les petits ensembles de résultats, je ne suis pas sûr que ce soit préférable. Pour les ensembles de résultats volumineux, EXISTS ne serait-il pas plus efficace?

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

vs.

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])
108
Randy Minder

EXISTS sera plus rapide car une fois que le moteur aura trouvé un hit, il cessera de regarder si la condition est vérifiée.

Avec IN, il collectera tous les résultats de la sous-requête avant tout traitement ultérieur.

134
keithwarren7

La réponse acceptée est à courte vue et la question un peu lâche en ce sens que:

1) N'indiquez pas explicitement si un indice de couverture est présent à gauche, à droite ou des deux côtés.

2) Ni l’un ni l’autre ne prend en compte la taille du jeu du côté gauche et du jeu du côté droit.
(La question mentionne simplement un grand ensemble résultat).

Je pense que l'optimiseur est suffisamment intelligent pour permettre la conversion entre "in" vs "existe" lorsqu'il existe une différence de coût significative en raison de (1) et (2), sinon, il peut simplement être utilisé comme un indice (par exemple, il existe pour encourager l'utilisation de un index recherché sur le côté droit).

Les deux formulaires peuvent être convertis en formulaires de jointure en interne, inverser l'ordre de jointure et s'exécuter en tant que boucle, hachage ou fusion - en fonction du nombre estimé de lignes (à gauche et à droite) et de l'existence de l'index dans les côtés gauche, droit ou.

36
crokusek

J'ai effectué des tests sur SQL Server 2005 et 2008, et sur les serveurs EXISTS et IN de revenir avec le même plan d'exécution, comme d'autres l'ont indiqué. L'optimiseur est optimal. :)

Cependant, EXISTS, IN et JOIN peuvent parfois renvoyer des résultats différents si vous ne formulez pas votre requête correctement: http://weblogs.sqlteam.com/mladenp/archive/2007/05 /18/60210.aspx

35
Adam Nofsinger

Les plans d'exécution seront généralement identiques dans ces cas, mais vous ne saurez jamais vraiment jusqu'à ce que l'optimiseur prenne en compte tous les autres aspects des index, etc.

3
Cade Roux

Ainsi, IN n’est pas identique à EXISTS et ne produira pas le même plan d’exécution.

Habituellement, EXISTS est utilisé dans une sous-requête corrélée, ce qui signifie que vous joindrez la requête interne EXISTS à votre requête externe. Cela ajoutera plus d'étapes pour produire un résultat, car vous devez résoudre les jointures de requête externes et les jointures de requête internes puis faire correspondre leurs clauses where pour joindre les deux.

Habituellement, IN est utilisé sans corrélation de la requête interne avec la requête externe et cela peut être résolu en une seule étape (dans le meilleur des cas).

Considère ceci:

  1. Si vous utilisez IN et que le résultat de la requête interne correspond à des millions de lignes de valeurs distinctes, il sera probablement plus lent que EXISTS, dans la mesure où la requête EXISTS est performante (dispose des index appropriés pour rejoindre la requête externe).

  2. Si vous utilisez EXISTS et que la jointure avec votre requête externe est complexe (prend plus de temps, pas d'index appropriés), la requête sera ralentie du nombre de lignes de la table externe, mais le temps estimé pour son exécution peut parfois être exprimé en jours. Si le nombre de lignes est acceptable pour votre matériel donné ou si la cardinalité des données est correcte (par exemple, moins de valeurs DISTINCT dans un ensemble de données volumineux), IN peut fonctionner plus rapidement que EXISTS.

  3. Tout ce qui est mentionné ci-dessus sera noté lorsque vous aurez une bonne quantité de lignes sur chaque table (j'entends juste ce que je veux dire par quelque chose qui dépasse votre traitement CPU et/ou les seuils de RAM pour la mise en cache).

Donc, la RÉPONSE est-elle DÉPENDUE. Vous pouvez écrire une requête complexe à l'intérieur de IN ou EXISTS, mais en règle générale, vous devez essayer d'utiliser IN avec un ensemble limité de valeurs distinctes et EXISTS lorsque vous avez beaucoup de lignes avec beaucoup de valeurs distinctes.

L'astuce consiste à limiter le nombre de lignes à analyser.

Cordialement,

MarianoC

3
MarianoC

J'irais avec EXISTS sur IN, voir le lien ci-dessous:

SQL Server: JOIN vs IN vs EXISTS - la différence logique

3
Tanner

Pour optimiser le EXISTS, soyez très littéral; il faut que quelque chose soit là, mais vous n'avez pas besoin de données renvoyées par la sous-requête corrélée. Vous évaluez simplement une condition booléenne.

Alors:

WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

Comme la sous-requête corrélée est RBAR, le premier résultat obtenu rend la condition vraie et elle n'est plus traitée.

1
Josh Lewis

Il y a beaucoup de réponses trompeuses ici, y compris celle qui est très élevée (bien que je ne pense pas que leurs opérations ont été dommageables). La réponse courte est: Ce sont les mêmes.

Il existe de nombreux mots-clés dans le langage (T) SQL, mais au final, la seule chose qui se passe réellement sur le matériel réside dans les opérations décrites dans le plan de requête d'exécution.

L'opération relationnelle (théorie mathématique) que nous faisons lorsque nous appelons [NOT] IN et [NOT] EXISTS est la semi-jointure (anti-jointure lorsqu’on utilise NOT). Ce n'est pas un hasard si les opérations correspondantes du serveur SQL ont le même nom. Il n'y a aucune opération qui mentionne IN ou EXISTS n'importe où - uniquement des (anti) semi-jointures. Ainsi, il n’ya aucun moyen qu’un choix IN vs EXISTS logiquement équivalent puisse affecter les performances car il existe un seul et même moyen, le (anti) semi rejoindre l'opération d'exécution, pour obtenir leurs résultats .

Un exemple:

Requête 1 ( plan )

select * from dt where dt.customer in (select c.code from customer c where c.active=0)

Requête 2 ( plan )

select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)
1
George Menoutis