Was ist besser: viele Join-Bedingungen oder viele Where-Bedingungen?

13

Ich versuche zwei Fragen zu vergleichen:

Abfrage 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 

Abfrage 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 

Bin ich richtig zu sagen, dass diese beiden Abfragen die gleichen Ergebnisse liefern?

Ist es richtig zu sagen, dass die erste Abfrage eine größere Tabelle erstellt, für die eine größere WHEREBedingung erfüllt werden soll? Im zweiten Fall haben wir eine kleinere konstruierte Tabelle, auf die dann das Einfache WHEREangewendet wird.

Welche Abfrage sollte bei gleichem Ergebnis bevorzugt werden? Gibt es ein offensichtliches Leistungsproblem?

Geoff
quelle
3
Nein, das sagst du nicht richtig. Es wäre, wenn das ein wäre INNER JOIN, aber mit einem wird LEFT JOINdies unterschiedliche Ergebnisse zurückgeben. Grundsätzlich WHEREkonvertieren die Bedingungen, die Sie in Ihrer zweiten Abfrage hinzugefügt haben, Ihre JOINauf einemINNER JOIN
Lamak
Ach ok Ich folge, was du sagst. Wenn ich INNER JOINmeine Fragen zur Leistung bearbeite, bleiben sie gültig?
Geoff
4
Für INNER JOINs sollte es keinen Leistungsunterschied geben. Aus Gründen der Lesbarkeit und Ausdrucksfähigkeit sollten Sie jedoch Join - Kriterien in ONund Filterkriterien in verwenden WHERE.
Aaron Bertrand
@ypercube richtig, ich habe diesen Zustand verpasst.
Lamak

Antworten:

10

Wenn wir davon ausgehen, dass Sie INNER JOINanstelle von LEFT JOIN(was Ihre Absicht zu sein scheint) verwenden, sind diese beiden Abfragen funktional gleichwertig. Abfrageoptimierer überprüfen und bewerten die Kriterien in Ihrer WHEREKlausel und in Ihrer FROMKlausel und berücksichtigen alle diese Faktoren beim Erstellen von Abfrageplänen, um den effizientesten Ausführungsplan zu erzielen. Wenn wir EXPLAINzu beiden Anweisungen eine machen, erhalten wir das gleiche Ergebnis:

Abfrage 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

[Ergebnisse] :

| 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 |

Abfrage 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

[Ergebnisse] :

| 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 |

Sie können die vollständigen Details unter den folgenden Links einsehen. Ich habe auch ein SQL 2008-Beispiel erstellt, damit Sie vergleichen können, wie die beiden Engines funktionieren (was dasselbe ist):

Beispiel für eine MySQL-Abfrage

SQL 2008-Abfragebeispiel (Stellen Sie sicher, dass Sie für beide Ergebnisse den Ausführungsplan anzeigen.)

Mike Fal
quelle
Vielen Dank für Ihre detaillierte Lösung. Ich habe es INNER JOINstattdessen versucht LEFT JOINund erhalte in einem Zehntel der Zeit die gleiche Ausgabe. Ich denke, ich weiß, warum ich die gleiche Ausgabe erhalte, aber warum hätte eine INNER JOINbessere Leistung?
Geoff
4
Da LEFT JOINes sich um einen Outer-Join handelt, kann er die Datenmenge auf der vollständigen Rückgabeseite der Menge nicht einschränken und versucht, alle Zeilen aus dieser Tabelle (in diesem Fall TableA) abzurufen. Wenn Sie verwenden INNER JOIN, kann es diese Kriterien für beide Tabellen nutzen und den Datensatz einschränken, wodurch eine schnellere Rendite erzielt wird.
Mike Fal