Quale è meglio: molte condizioni di partecipazione o molte dove condizioni?


13

Sto cercando di confrontare due query:

Query 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 

Query 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 

Ho ragione a dire che queste due domande danno gli stessi risultati?

Inoltre, è corretto affermare che la prima query crea una tabella più grande per la quale eseguire una WHEREcondizione più grande ; mentre nel secondo caso abbiamo una tabella costruita più piccola alla quale WHEREviene quindi applicato il semplice .

Supponendo che i risultati siano gli stessi, quale query dovrebbe essere preferita? C'è un evidente problema di prestazioni?


3
No, non hai ragione a dirlo. Sarebbe se quello fosse un INNER JOIN, ma con LEFT JOINquesto restituirà risultati diversi. Fondamentalmente, le condizioni che hai aggiunto sulla WHEREtua seconda query stanno convertendo il tuo JOINsuINNER JOIN
Lamak

Ah ok. Seguo quello che dici. Se modifico per INNER JOINrendere valide le mie domande sulle prestazioni?
Geoff,

4
Per INNER JOINs non ci dovrebbero essere differenze nelle prestazioni. Detto questo, per la leggibilità e la corretta espressione dell'intento, è necessario utilizzare i criteri di join nei criteri di ONfiltro e nella WHERE.
Aaron Bertrand

@ypercube giusto, mi mancava quella condizione.
Lamak,

Risposte:


10

Se consideriamo che usi INNER JOINinvece di LEFT JOIN(che sembra essere il tuo intento), queste due query sono funzionalmente equivalenti. Gli ottimizzatori di query riesamineranno e valuteranno i criteri nella tua WHEREclausola e nella tua clausola e terranno FROMconto di tutti questi fattori durante la costruzione di piani di query al fine di raggiungere il piano di esecuzione più efficiente. Se facciamo EXPLAINentrambe le affermazioni, otteniamo lo stesso risultato:

Query 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

[Risultati] :

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

Query 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

[Risultati] :

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

È possibile rivedere i dettagli completi con i seguenti collegamenti. Ho anche creato un esempio di SQL 2008 in modo da poter confrontare il funzionamento dei due motori (che è lo stesso):

Esempio di query MySQL

Esempio di query SQL 2008 (assicurati di 'Visualizza piano di esecuzione' per entrambi i risultati)


Grazie per la tua soluzione dettagliata. Ho provato INNER JOINinvece LEFT JOINe ottengo lo stesso risultato in un decimo del tempo. Penso di sapere perché ottengo lo stesso output, ma perché dovrei avere INNER JOINprestazioni migliori?
Geoff,

4
Come LEFT JOINun join esterno, non può limitare il set di dati sul lato di ritorno completo del set e tenterà di recuperare tutte le righe da quella tabella (in questo caso, TableA). Se lo si utilizza INNER JOIN, può sfruttare tali criteri su entrambe le tabelle e limitare il set di dati, fornendo così un ritorno più rapido.
Mike Fal,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.