Question

Je suis curieuse de ce qui suit serait ci-dessous plus efficace?

J'ai toujours été un peu prudent sur l'utilisation IN parce que je crois que SQL Server transforme le jeu de résultats dans une grande déclaration de IF. Pour un grand jeu de résultats, cela pourrait entraîner de mauvaises performances. Pour les petits ensembles de résultats, je ne suis pas sûr non plus est préférable. Pour de grands résultats, ne serait pas EXISTS être 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])
Était-ce utile?

La solution

EXISTS sera plus rapide car une fois que le moteur a trouvé un coup, il quittera la recherche que la condition a prouvé vrai.

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

Autres conseils

La réponse acceptée est myope et la question un peu lâche en ce que:

  

1) Ni mentionner explicitement si un indice de couverture est présent dans   gauche, à droite, ou les deux côtés.

     

2) Ni prend en compte la taille du jeu de côté gauche d'entrée et   entrée de jeu côté droit.
        (La question mentionne juste un grand ensemble Résultat set).

Je crois que l'optimiseur est assez intelligent pour convertir entre « dans » vs « existe » quand il y a une différence significative des coûts en raison de (1) et (2), sinon il peut juste être utilisé comme un indice (par exemple, existe à encourager l'utilisation d'un indice positionnable sur le côté droit).

Les deux formes peuvent être converties à se joindre à des formes internes, ont l'ordre de jointure inversé, et courir comme boucle, hachage ou fusion - d'après les chiffres de ligne estimés (gauche et droite) et l'existence d'index gauche, à droite, ou les deux côtés.

Je l'ai fait quelques tests sur SQL Server 2005 et 2008, et sur les deux et la EXISTE EN revenir au plan même de l'exécution réelle exacte, que d'autres ont déclaré. L'Optimiseur est optimale. :)

Quelque chose à prendre en compte si, EXISTS, IN et assemblez peut parfois renvoyer des résultats différents si vous n'avez pas votre phrase requête juste: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

Je partirais avec EXISTE sur IN, voir lien ci-dessous:

SQL Server: JOIN IN vs vs EXISTE - logique différence

Les plans d'exécution sont généralement identiques vont être dans ces cas, mais jusqu'à ce que vous voyez comment les facteurs d'optimisation dans tous les autres aspects des index, etc., vous ne saurez jamais vraiment.

Alors, IN est pas le même que EXISTE ni elle produira le même plan d'exécution.

Habituellement EXISTE est utilisé dans une sous-requête corrélée, cela signifie que vous vous joindrez à la requête EXISTS intérieure avec votre requête externe. Cela ajoutera plusieurs étapes pour produire un résultat que vous avez besoin pour résoudre la requête jointures externes et la requête intérieure correspond alors leur rejoint où les clauses de se joindre à la fois.

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

Considérez ceci:

  1. Si vous utilisez IN et le résultat de la requête interne est des millions de lignes de valeurs distinctes, il sera probablement effectuer LENT que EXISTS étant donné que la EXISTE requête est performant (a les index droit à se joindre à la requête externe).

  2. Si vous utilisez EXISTE et la jointure avec votre requête externe est complexe (prend plus de temps pour effectuer, aucun index approprié), il va ralentir la requête par le nombre de lignes dans la table externe, parfois le temps estimé à complète peut être en quelques jours. Si le nombre de lignes est acceptable pour votre matériel donné ou la cardinalité de données sont correctes (par exemple moins de valeurs DISTINCTS dans un grand ensemble de données) IN peuvent effectuer plus rapidement que EXISTE.

  3. Tous les ci-dessus sera indiqué lorsque vous avez une bonne quantité de lignes sur chaque table (par juste que je veux dire quelque chose qui dépasse le traitement de votre CPU et / ou des seuils de RAM pour la mise en cache).

La réponse est-il DÉPEND. Vous pouvez écrire une requête complexe à l'intérieur IN ou EXISTE, mais en règle générale, vous devriez essayer d'utiliser IN avec un nombre limité de valeurs distinctes et EXISTE lorsque vous avez beaucoup de lignes avec beaucoup de valeurs distinctes.

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

Cordialement,

MarianoC

Pour optimiser le EXISTS, très littérale; quelque chose doit juste être là, mais vous ne fait pas besoin de données renvoyées par la sous-requête corrélée. Vous êtes juste évaluation d'une condition booléenne.

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

Parce que la sous-requête est corrélative RBAR, le premier coup de résultat rend la condition vrai, et il est traité sans autre.

Il y a beaucoup de réponses de réponses trompeuses ici, y compris celui très upvoted (bien que je ne crois pas que leurs ops voulait du mal). La réponse courte est: Ce sont les mêmes

.

Il y a beaucoup de mots-clés dans le (T-) langage SQL, mais à la fin, la seule chose qui se passe réellement sur le matériel est les opérations comme on le voit dans le plan de requête d'exécution.

Le relationnel opération (théorie mathématique) que nous faisons lorsque nous invoquons [NOT] IN et [NOT] EXISTS est le demi JOIN (anti-jointure avec NOT). Ce n'est pas une coïncidence si les opérations sql-serveur correspondant ont le même nom . Il n'y a aucune opération qui mentionne IN ou EXISTS partout - que (anti-) semi-joint. Ainsi, il n'y a aucun moyen qu'un IN logiquement équivalent vs choix EXISTS pourrait affecter les performances car il est seul et unique moyen, le (anti) semi-opération de jointure d'exécution, pour obtenir leurs résultats .

Un exemple:

Requête 1 ( )

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

Requête 2 ( )

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

Du haut de ma tête et non garantis correctes: Je crois que le second sera plus rapide dans ce cas.

  1. Dans la première, la sous-requête corrélée entraînera probablement la sous-requête à exécuter pour chaque ligne.
  2. Dans le second exemple, la sous-requête ne devrait fonctionner une fois, car non corrélées.
  3. Dans le second exemple, le IN sera court-circuit dès qu'il trouve une correspondance.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top