Performances SQL JOIN vs IN?


164

J'ai un cas où l'utilisation d'un JOIN ou d'un IN me donnera les bons résultats ... Qui a généralement de meilleures performances et pourquoi? Dans quelle mesure cela dépend-il du serveur de base de données que vous utilisez? (Pour info j'utilise MSSQL)


:) Je cherchais en fait un article différent que j'ai utilisé lorsque j'ai fait des recherches sur quelque chose de similaire il y a quelque temps, et je suis tombé sur celui-là par erreur
AdaTheDev

Désolé pour la possible dupe ... je n'ai pas trouvé cette question lorsque je cherchais
Polaris878

Réponses:


197

De manière générale, INil JOINexiste différentes requêtes qui peuvent donner des résultats différents.

SELECT  a.*
FROM    a
JOIN    b
ON      a.col = b.col

n'est pas la même chose que

SELECT  a.*
FROM    a
WHERE   col IN
        (
        SELECT  col
        FROM    b
        )

, sauf s'il b.colest unique.

Cependant, c'est le synonyme de la première requête:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT col
        FROM    b
        )
ON      b.col = a.col

Si la colonne de jonction est UNIQUEet marquée comme telle, ces deux requêtes génèrent le même plan dans SQL Server.

Si ce n'est pas le cas, alors INc'est plus rapide que JOINsur DISTINCT.

Voir cet article dans mon blog pour plus de détails sur les performances:


Ouais, il est logique qu'ils exécutent la même chose si la colonne de jonction est unique (ce qui est dans mon cas)
Polaris878

1
Sur une note similaire, devrais-je utiliser IN (SELECT DISTINCT ...) ou simplement IN (SELECT ...)?
moo

8
@ orlandu63: INimplique DISTINCT. SQL Serverest assez intelligent pour le remarquer et générera les mêmes plans pour les deux requêtes. Je ne sais pas comment les autres RDBMSse comporteront.
Quassnoi le

>> IN et JOIN sont des requêtes différentes qui peuvent donner des résultats différents. Pouvez-vous expliquer pourquoi cela générerait-il un résultat différent dans ce cas même si b.col n'est pas unique?
Abhijeet



6

C'est assez difficile à dire - pour vraiment savoir lequel fonctionne le mieux, vous devez réellement profiler les temps d'exécution.

En règle générale, je pense que si vous avez des index sur vos colonnes de clé étrangère, et si vous utilisez uniquement (ou principalement) des conditions INNER JOIN, alors le JOIN sera légèrement plus rapide.

Mais dès que vous commencez à utiliser OUTER JOIN, ou si vous manquez d'index de clé étrangère, IN peut être plus rapide.

Marc


Je pensais cela aussi ... parce qu'il semble que JOIN est un cas plus courant et serait plus probablement optimisé
Polaris878

4

Un article intéressant sur les différences logiques: SQL Server: JOIN vs IN vs EXISTS - la différence logique

Je suis presque sûr qu'en supposant que les relations et les index sont maintenus, une jointure fonctionnera mieux dans l'ensemble (plus d'efforts sont consacrés à cette opération par rapport aux autres). Si vous y réfléchissez conceptuellement, c'est la différence entre 2 requêtes et 1 requête.

Vous devez le connecter à l'Analyseur de requêtes et l'essayer et voir la différence. Consultez également le plan d'exécution des requêtes et essayez de minimiser les étapes.


4

Ce fil est assez ancien mais toujours mentionné souvent. Pour mon goût personnel, c'est un peu incomplet, car il existe une autre façon de demander à la base de données avec le mot-clé EXISTS que j'ai trouvé plus rapide le plus souvent.

Donc, si vous n'êtes intéressé que par les valeurs de la table a, vous pouvez utiliser cette requête:

SELECT  a.*
FROM    a
WHERE   EXISTS (
    SELECT  *
    FROM    b
    WHERE   b.col = a.col
    )

La différence peut être énorme si col n'est pas indexé, car la base de données n'a pas besoin de trouver tous les enregistrements dans b qui ont la même valeur dans col, il doit seulement trouver le tout premier. S'il n'y a pas d'index sur b.col et que beaucoup d'enregistrements dans l'analyse de la table ba peuvent en être la conséquence. Avec IN ou un JOIN, ce serait un balayage complet de la table, avec EXISTS ce ne serait qu'un balayage partiel de la table (jusqu'à ce que le premier enregistrement correspondant soit trouvé).

S'il y a beaucoup d'enregistrements dans b qui ont la même valeur col, vous gaspillerez également beaucoup de mémoire pour lire tous ces enregistrements dans un espace temporaire juste pour constater que votre condition est satisfaite. Avec existe, cela peut être généralement évité.

J'ai souvent trouvé EXISTS plus rapide que IN même s'il y a un index. Cela dépend du système de base de données (l'optimiseur), des données et surtout du type d'index utilisé.


3
Sur MSSql, le fait qu'il existe est meilleur qu'un IN ne semble pas vrai. Pour plus d'informations: describeextended.com/2009/06/16/in-vs-join-vs-exists Ici, vous pouvez lire que: "Beaucoup pensent qu'EXISTS est plus efficace que IN, car EXISTS ne renvoie qu'une seule ligne. C'est pas vrai pour SQL Server. Comme nous pouvons le voir dans les exemples ci-dessus, EXISTS et IN produisent exactement les mêmes plans. En effet, EXISTS est plus flexible que IN. Un IN peut toujours être réécrit comme EXISTS (en utilisant une simple condition WHERE avec une équi-jointure ) mais pas l'inverse. "
Micaël Félix

3

L'implémentation de chaque base de données, mais vous pouvez probablement deviner qu'elles résolvent toutes les problèmes courants plus ou moins de la même manière. Si vous utilisez MSSQL, jetez un œil au plan d'exécution généré. Vous pouvez le faire en activant le profileur et les plans d'exécution. Cela vous donnera une version texte lorsque vous exécuterez la commande.

Je ne sais pas quelle version de MSSQL vous utilisez, mais vous pouvez en obtenir une graphique dans SQL Server 2000 dans l'analyseur de requêtes. Je suis sûr que cette fonctionnalité se cache quelque part dans SQL Server Studio Manager dans les versions ultérieures.

Jetez un œil au plan d'exeuction. Dans la mesure du possible, évitez les analyses de table à moins bien sûr que votre table ne soit petite, auquel cas une analyse de table est plus rapide que d'utiliser un index. Renseignez-vous sur les différentes opérations de jointure produites par chaque scénario différent.


1

L'optimiseur doit être suffisamment intelligent pour vous donner le même résultat dans les deux cas pour les requêtes normales. Vérifiez le plan d'exécution et ils devraient vous donner la même chose. Si ce n'est pas le cas, je considérerais normalement que le JOIN est plus rapide. Cependant, tous les systèmes sont différents, vous devez donc profiler le code sur votre système pour en être sûr.


5
Devrait faire? Peut être. Le fait-il? Non. Voir mon message.
cletus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.