Jointure interne vs où

257

Existe-t-il une différence de performances (dans Oracle) entre

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

Et

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?

juan
la source
1
juste pour mémoire, j'ai vu des requêtes renvoyer des résultats différents uniquement en passant d'une jointure à une clause
where
12
@BlackTigerX: Des résultats différents? Y avait-il des jointures externes impliquées? Parce que je ne vois pas comment des résultats différents se produiraient entre un inner join ... onet la mise en place de critères de jointure équivalents dans la whereclause.
Shannon Severance
dans l'ancienne version de la base de données oracle n'existe pasjoin
MajidTaheri
2
@MajidTaheri: quel âge d'une version d'Oracle parlez-vous? Toute version prise en charge par Oracle prend en charge la notation JOIN.
Jonathan Leffler
Recherchez les réponses générales ou les meilleures pratiques basées sur des cas triviaux. Voudrait voir un "re-match" avec des clauses where plus complexes impliquant plusieurs conditions AND'd. Au moins avec SQL Server, il existe un point de croisement.
crokusek

Réponses:

195

Non! Le même plan d'exécution, regardez ces deux tableaux:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

Plan d'exécution de la requête à l'aide de la jointure interne:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

Et le plan d'exécution de la requête à l'aide d'une clause WHERE.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2
kiewic
la source
4
Je souhaite vraiment voir s'il existe des documents officiels d'Oracle à ce sujet
4 Quitter la couverture
68

Si l'optimiseur de requêtes fait bien son travail, il ne devrait pas y avoir de différence entre ces requêtes. Ce ne sont que deux façons de spécifier le même résultat souhaité.

Craig Trader
la source
22
Oui, les performances devraient être les mêmes. Mais la syntaxe SELECT * FROM Table1, Table2 WHERE ... est EVIL!
Joel Coehoorn
2
Je trouve qu'il est beaucoup plus facile de comprendre FOR INNER JOINS que la syntaxe SQL-92. Votre kilométrage peut varier.
Craig Trader
25
Je trouve que la syntaxe WHERE est plus facile à lire que INNER JION - je suppose que c'est comme Vegemite. La plupart des gens dans le monde le trouvent probablement dégoûtant, mais les enfants ont grandi en le mangeant l'adorent.
ScottCher
3
Vegemite est vraiment méchant, mais là encore j'adore la scrapple. Allez comprendre.
StingyJack
2
@Darryl Je pense que les JOINs sont plus faciles à lire car la condition pour joindre les tables est définie juste là au lieu de "quelque part" dans la WHEREclause. Je préfère réserver la WHEREclause pour limiter l'ensemble de données (par exemple WHERE DATE > (SYSDATE - 1)) au lieu de définir également comment les tables sont liées les unes aux autres (par exemple WHERE T1.ID = T2.ID). Pour une petite table comme l'exemple en question fait peu de différence, mais pour les grandes requêtes impliquant plusieurs tables et plusieurs conditions, je pense que cela rend la requête beaucoup plus facile à comprendre.
ImaginaryHuman072889
61

Ils devraient être exactement les mêmes. Cependant, en tant que pratique de codage, je préfère voir la jointure. Il exprime clairement votre intention,

Nescio
la source
8
Je suis d'accord. Surtout si vous vous joignez à plusieurs tables, il est beaucoup plus facile d'analyser une instruction select si vous effectuez des jointures explicites.
Paul Morie
13
En effet. Les jointures représentent une relation sémantique entre deux ensembles de données mais un où suggère un ensemble filtré. +1
EightyOne Unite
26

En utilisant JOIN rend le code plus facile à lire, car il est explicite.

Il n'y a pas de différence de vitesse ( je viens de le tester ) et le plan d'exécution est le même.

user21241
la source
Je vous remercie. je cherchais une compression de vitesse entre ces deux méthodes.
Farhad Navayazdan
14

Je ne connais pas Oracle mais je sais que l'ancienne syntaxe est déconseillée dans SQL Server et disparaîtra finalement. Avant d'utiliser cette ancienne syntaxe dans une nouvelle requête, je vérifiais ce que Oracle prévoyait d'en faire.

Je préfère la nouvelle syntaxe plutôt que le mélange des critères de jointure avec d'autres conditions nécessaires. Dans la nouvelle syntaxe, il est beaucoup plus clair ce qui crée la jointure et quelles autres conditions sont appliquées. Ce n'est pas vraiment un gros problème dans une courte requête comme celle-ci, mais cela devient beaucoup plus déroutant lorsque vous avez une requête plus complexe. Étant donné que les gens apprennent sur les requêtes de base, j'aurais tendance à préférer que les gens apprennent à utiliser la syntaxe de jointure avant d'en avoir besoin dans une requête complexe.

Et encore une fois, je ne connais pas spécifiquement Oracle, mais je sais que la version SQL Server de l'ancienne jointure gauche est défectueuse même dans SQL Server 2000 et donne des résultats incohérents (parfois une jointure gauche parfois une jointure croisée), donc elle ne devrait jamais être utilisé. Espérons que Oracle ne souffre pas du même problème, mais les jointures gauche et droite peuvent être plus difficiles à exprimer correctement dans l'ancienne syntaxe.

De plus, d'après mon expérience (et bien sûr, il s'agit strictement d'une opinion personnelle, vous pouvez avoir une expérience différente), les développeurs qui utilisent les jointures standard ANSII ont tendance à mieux comprendre ce qu'est une jointure et ce qu'elle signifie en termes d'obtention les données de la base de données. Je crois que c'est parce que la plupart des personnes ayant une bonne compréhension des bases de données ont tendance à écrire des requêtes plus complexes et celles-ci me semblent beaucoup plus faciles à maintenir en utilisant la norme ANSII que l'ancien.

HLGEM
la source
1
Amen frère. A bas les JOINTEURS !!
ScottCher
14

[Pour un point bonus ...]

L'utilisation de la syntaxe JOIN vous permet de commenter plus facilement la jointure car elle est tout inclus sur une seule ligne. Cela peut être utile si vous déboguez une requête complexe

Comme tout le monde le dit, ils sont fonctionnellement les mêmes, mais le JOIN est plus clair d'une déclaration d'intention. Cela peut donc aider l'optimiseur de requêtes dans les versions actuelles d'Oracle dans certains cas (je n'en ai aucune idée), il peut aider l'optimiseur de requêtes dans les futures versions d'Oracle (personne n'en a la moindre idée), ou il peut être utile si vous changez de fournisseur de base de données.

Chris Gill
la source
2
Ou ... changez facilement les JOINTURES INTÉRIEURES en JOINTURES GAUCHES, de sorte que vous voyez quelle jointure vous fait manquer des lignes attendues. Je le fais parce que je fais toute la requête en même temps. Si vous commentez INNER JOINS, vous devez en quelque sorte faire un processus d'élimination. Cela prend plus de temps. Mais +1 pour vous car c'est une de mes raisons préférées pour INNER JOINS en dehors de la lisibilité!
Matthew McPeak
13

Ils sont logiquement identiques, mais dans les versions antérieures d'Oracle qui adoptaient la syntaxe ANSI, il y avait souvent des bogues avec elle dans des cas plus complexes, vous rencontrerez donc parfois une résistance des développeurs Oracle lors de son utilisation.

David Aldridge
la source
Les versions antérieures d'Oracle avaient des bugs avec cela? Combien tôt? Quelle (s) version (s)?
ScottCher
Metalink a des détails ... ils apparaissent partout.
David Aldridge
7

Les performances devraient être identiques, mais je suggérerais d'utiliser la version join en raison d'une meilleure clarté en ce qui concerne les jointures externes.

Les produits cartésiens non intentionnels peuvent également être évités en utilisant la version join.

Un troisième effet est un SQL plus facile à lire avec une condition WHERE plus simple.

stili
la source
Je pense vraiment que la clé est des effets involontaires lorsque les critères sont ambigus. Si vous spécifiez le type de jointure, vous savez exactement ce que vous obtenez. J'ai constaté que différentes bases de données et même différentes versions de la même plate-forme de base de données gèrent différemment les valeurs nulles dans une jointure implicite. Lorsque vous spécifiez gauche / droite intérieure / extérieure, vous passez le temps de réfléchir à ce qui est correct. Lorsque vous utilisez la méthode ambiguë, vous supposez que cela fonctionne comme vous l'espérez / l'intention de le faire.
Steve Kallestad
6

N'oubliez pas que dans Oracle, à condition que les attributs de clé de jointure soient nommés de la même manière dans les deux tables, vous pouvez également écrire ceci comme:

select *
from Table1 inner join Table2 using (ID);

Cela a également le même plan de requête, bien sûr.

cheduardo
la source
J'ai annulé l'édition parce que la révision précédente a changé le sens de la réponse
juan
5

Dans un scénario où les tables sont en 3e forme normale, les jointures entre les tables ne doivent pas changer. C'est à dire rejoindre les CLIENTS et les PAIEMENTS doivent toujours rester les mêmes.

Cependant, nous devons distinguer les jointures des filtres . Les jointures concernent les relations et les filtres concernent le partitionnement d'un ensemble.

Certains auteurs, se référant à la norme (c.-à-d. Jim Melton; Alan R. Simon (1993). Understanding The New SQL: A Complete Guide. Morgan Kaufmann. Pp. 11–12. ISBN 978-1-55860-245-8.) , a écrit sur les avantages d'adopter la syntaxe JOIN sur les tables séparées par des virgules dans la clause FROM.

Je suis totalement d'accord avec ce point de vue.

Il existe plusieurs façons d'écrire SQL et d'obtenir les mêmes résultats, mais pour beaucoup de ceux qui travaillent en équipe, la lisibilité du code source est un aspect important, et séparer certainement la façon dont les tables se relient les unes aux autres à partir de filtres spécifiques a été un grand pas en avant dans la clarification de la source code.

abrittaf
la source
La jointure interne sur signifie la jointure croisée où. La virgule est une jointure croisée avec une priorité inférieure à celle des jointures de mots clés. On vs "filter" n'est pas pertinent pour la jointure interne. Les NF ne sont pas pertinentes pour l'interrogation. Rien dans la norme ne fait la promotion des jointures de mots clés plutôt que des virgules. Les optimisations triviales traitent sur et où de la même façon. Cette réponse est un tas d'idées fausses.
philipxy
1) Je suppose que @philipxy essaie de dire "Dans la clause FROM, les tables séparées par des virgules ont la même signification que les tables CROSS JOINed." Je suis d'accord avec ça. Bien sûr, vous pouvez vous en tenir à l'ancienne syntaxe et cela peut coexister avec les clauses JOIN. Les optimiseurs RDBMS comprendront parfaitement les deux cas comme étant identiques (au cas où ils sont bien sûr équivalents) et élaboreront le même plan.
abrittaf
4

Dans PostgreSQL, il n'y a certainement aucune différence - ils correspondent tous deux au même plan de requête. Je suis sûr à 99% que c'est également le cas pour Oracle.

Nick Johnson
la source
2

Ce sont deux jointures internes qui font la même chose, on utilise simplement la nouvelle syntaxe ANSI.

Bob Gettys
la source
2

Fonctionnellement, ils sont identiques à ce qui a été dit. Je suis d'accord cependant que faire la jointure est préférable pour décrire exactement ce que vous voulez faire. Beaucoup de fois, j'ai pensé que je savais comment je voulais interroger quelque chose jusqu'à ce que je commence à faire les jointures et j'ai réalisé que je voulais faire une requête différente de celle d'origine dans ma tête.

MattC
la source
1

Il est vrai que, fonctionnellement, les deux requêtes doivent être traitées de la même manière. Cependant, l'expérience a montré que si vous sélectionnez à partir de vues qui utilisent la nouvelle syntaxe de jointure, il est important de structurer vos requêtes en l'utilisant également. L'optimiseur d'Oracle peut être confus si une vue utilise une instruction "join", mais une requête accédant à la vue utilise la méthode traditionnelle de jointure dans la clause "where".

JoshL
la source
C'est plus un problème avec les vues qu'avec les jointures.
exister le
0

Bien que l'identité de deux requêtes semble évidente, parfois des choses étranges se produisent. Je suis tombé sur la requête qui a différents plans d'exécution lors du déplacement du prédicat de jointure de JOIN vers WHERE dans Oracle 10g (pour le plan WHERE, c'est mieux), mais je ne peux pas reproduire ce problème dans des tableaux et des données simplifiés. Je pense que cela dépend de mes données et statistiques. L'optimiseur est un module assez complexe et il se comporte parfois comme par magie.

C'est pourquoi nous ne pouvons pas répondre à cette question en général car cela dépend des internes DB. Mais nous devons savoir que la réponse doit être « aucune différence ».

greatvovan
la source
0

j'ai eu cette énigme aujourd'hui lors de l'inspection de l'un des délais de production de notre sp, changé une jointure interne sur une table construite à partir d'un flux xml en une clause `` où '' à la place .... le temps d'exécution moyen est maintenant de 80 ms sur 1000 exécutions, tandis que avant que le taux d'exécution moyen ne soit de 2,2 secondes ... la principale différence dans le plan d'exécution est la disparition d'une recherche de clé ... Le message étant que vous ne saurez pas jusqu'à ce que vous ayez testé en utilisant les deux méthodes.

à votre santé.

trbullet81
la source
0

Comme l'a dit Kiewik, le plan d'exécution est le même.

L'instruction JOIN est seulement plus facile à lire, ce qui permet de ne pas oublier la condition ON et d'obtenir un produit cartésien. Ces erreurs peuvent être assez difficiles à détecter dans les longues requêtes utilisant plusieurs jointures de type: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Si vous oubliez une seule condition de jointure, vous obtenez une requête d'exécution très longue renvoyant trop d'enregistrements ... vraiment trop. Certains poeple utilisent un DISTINCT pour patcher la requête, mais son exécution est encore très longue.

C'est précisément pourquoi, l'utilisation de l'instruction JOIN est certainement la meilleure pratique: une meilleure maintenabilité et une meilleure lisibilité.

De plus, si je me souviens bien, JOIN est optimisé en ce qui concerne l'utilisation de la mémoire.

ROQUEFORT François
la source
0

J'ai un ajout à cette bonne réponse :

C'est ce qui est défini comme SQL92 et SQL89 respectivement, il n'y a pas de différence de performances entre eux bien que vous puissiez omettre le mot INNER (en utilisant simplement JOIN est assez clair et dans la requête la plus simple vous enregistrez 5 coups de clavier, imaginez maintenant combien de coups il y a en gros les uns).

Ivanzinho
la source