Quel est le meilleur: beaucoup de conditions d'adhésion ou beaucoup de conditions?

13

J'essaie de comparer deux requêtes:

Requête 1:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a
WHERE tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  AND tableA.e=tableB.e 

Requête 2:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a AND tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  
WHERE tableA.e=tableB.e 

Ai-je raison de dire que ces deux requêtes donnent les mêmes résultats?

De plus, est-il correct de dire que la première requête construit une table plus grande pour laquelle effectuer une WHEREcondition plus grande ; tandis que le deuxième cas, nous avons une table construite plus petite à laquelle le simple WHEREest ensuite appliqué.

En supposant que les résultats sont les mêmes, quelle requête doit être préférée? Y a-t-il un problème de performance évident?

Geoff
la source
3
Non, vous n'avez pas raison de dire cela. Ce serait le cas si c'était un INNER JOIN, mais avec un LEFT JOINcela retournera des résultats différents. Fondamentalement, les conditions que vous avez ajoutées sur le WHEREsur votre deuxième requête convertissent votre JOINsur unINNER JOIN
Lamak
Ah ok. Je suis ce que tu dis. Si je modifie pour INNER JOINque mes questions sur les performances restent valables?
Geoff
4
Pour les jointures internes, il ne devrait pas y avoir de différence de performances. Cela dit, pour la lisibilité et l'expression correcte de l'intention, vous devez utiliser les critères de jointure dans le ONet les critères de filtre dans le WHERE.
Aaron Bertrand
@ypercube à droite, j'ai raté cette condition.
Lamak

Réponses:

10

Si nous considérons que vous utilisez à la INNER JOINplace de LEFT JOIN(ce qui semble être votre intention), ces deux requêtes sont fonctionnellement équivalentes. Les optimiseurs de requête examineront et évalueront les critères de votre WHEREclause et de votre FROMclause et prendront en compte tous ces facteurs lors de la création de plans de requête afin d'atteindre le plan d'exécution le plus efficace. Si nous faisons un EXPLAINsur les deux instructions, nous obtenons le même résultat:

Requête 1 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
WHERE 
  tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
  AND tableA.ColE=tableB.ColE

[Résultats] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Requête 2 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
  AND tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
WHERE
  tableA.ColE=tableB.ColE

[Résultats] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Vous pouvez consulter tous les détails avec les liens suivants. J'ai également créé un exemple SQL 2008 afin que vous puissiez comparer le fonctionnement des deux moteurs (qui est le même):

Exemple de requête MySQL

Exemple de requête SQL 2008 (assurez-vous de «Afficher le plan d'exécution» pour les deux résultats)

Mike Fal
la source
Merci pour votre solution détaillée. J'ai essayé INNER JOINau lieu de LEFT JOINet j'obtiens la même sortie dans un dixième du temps. Je pense que je sais pourquoi j'obtiens la même sortie, mais pourquoi aurait une INNER JOINmeilleure performance?
Geoff
4
Comme LEFT JOINc'est une jointure externe, elle ne peut pas restreindre l'ensemble de données sur le côté retour complet de l'ensemble et essaiera de récupérer toutes les lignes de cette table (dans ce cas, TableA). Si vous utilisez INNER JOIN, il peut tirer parti de ces critères sur les deux tables et restreindre l'ensemble de données, offrant ainsi un retour plus rapide.
Mike Fal