Utilizzo della parola chiave JOIN o no

40

Le seguenti query SQL sono le stesse:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

E certamente si traducono negli stessi piani di query su ogni DBMS che abbia mai provato.

Ma ogni tanto, leggo o sento un'opinione che si è decisamente meglio rispetto agli altri. Naturalmente, queste affermazioni non sono mai confermate da un spiegazione.

Dove lavoro, la seconda versione sembra essere favorita dalla maggior parte delle altre devs, e quindi tendo anche a quello stile per minimizzare la sorpresa. Ma nel mio cuore, sto davvero pensando al primo (poiché è così che ho imparato in origine esso).

Una di queste forme è obiettivamente migliore dell'altra? In caso contrario, quali sarebbero i motivi per utilizzare l'uno sull'altro?

    
posta SingleNegationElimination 22.05.2011 - 03:19
fonte

9 risposte

57

Trovo che la seconda forma sia migliore. Forse perché è così che l'ho imparato, lo ammetto, ma ho una ragione concreta: la separazione delle preoccupazioni. Mettere i campi che stai utilizzando per unire le tabelle nella clausola where può portare a difficoltà nel comprendere le query.

Ad esempio, prendi la seguente domanda:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

La query precedente ha condizioni di congiunzione delle tabelle e condizioni di business logic effettive tutte combinate in un unico spazio. Con una query di grandi dimensioni, questo può essere molto difficile da capire.

Tuttavia, ora prendi questo codice:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

In questo caso, tutto ciò che ha a che fare con le tabelle o il modo in cui si relazionano è tutto isolato dalla clausola from, mentre la logica aziendale effettiva per la restrizione delle query è contenuta nella clausola where. Penso che sia molto più comprensibile, in particolare per le query più grandi.

    
risposta data 22.05.2011 - 03:27
fonte
36

La sintassi del join sostituiva la vecchia sintassi della virgola nel 1992. Attualmente non esiste alcun motivo per scrivere codice con la sintassi della virgola. Non ottieni nulla e sei soggetto ad alcuni problemi che semplicemente non hai con sintassi esplicita.

In primo luogo quando si ottengono query più complicate è molto facile eseguire un cross join accidentale perché manca una condizione where. Questo è qualcosa che la sintassi esplicita del join può impedire che si verifichi poiché si verificherà un errore di sintassi.

Se si intende un cross join, la sintassi esplicita del join lo renderà chiaro mentre nella sintassi implicita qualcuno che sta eseguendo la manutenzione potrebbe assumere che si è dimenticato di aggiungere la clausola where.

Poi c'è il problema dei join sinistro e destro che sono problematici in almeno alcuni dbs che usano la sintassi implicita. Sono deprecati in SQL Server e infatti non restituiscono risultati corretti in modo affidabile anche nelle versioni precedenti. Nessuna query che richiede un join esterno dovrebbe contenere la sintassi implicita in SQL Server.

Inoltre, ho visto domande qui e su altri siti in cui si sono verificati risultati errati quando le persone mescolano i join impliciti ed espliciti (quando si aggiunge un join sinistro per esempio), quindi è una cattiva idea mescolarli.

Finalmente molte persone che usano i join impliciti in realtà non capiscono i join. Questa è una comprensione critica che devi avere per interrogare efficacemente un database.

    
risposta data 22.05.2011 - 04:57
fonte
7

Ha. Mi è capitato di trovare una possibile risposta alla mia domanda, mentre osservavo la documentazione di PostgreSQL . Per riassumere ciò che questa pagina spiega, la query risultante è sempre la stessa, ma il numero di piani che l'ottimizzatore deve considerare cresce in modo esponenziale con il numero di join.

Dopo circa sei join di questo tipo, il numero è così grande che il tempo per pianificare la query potrebbe essere evidente e, dopo circa dieci, l'ottimizzatore passerà da una ricerca esauriente di piani a una ricerca probabilistica e potrebbe non arrivare a il piano ottimale.

Impostando un parametro run-time, puoi istruire il pianificatore a trattare i join interni e incrociati espressamente menzionati in modo diverso dai join impliciti, forzandoli in cima al piano e non esplorando altre opzioni.

Da notare, il comportamento predefinito è lo stesso in entrambi i casi, e che ottenere piani alternativi richiede la conoscenza degli interni del dbms e delle peculiarità delle tabelle in questione per ottenere un risultato diverso

    
risposta data 22.05.2011 - 04:04
fonte
7

Bene, ecco la visione della teoria degli insiemi:

Quando si utilizza una virgola per separare due (o più) nomi di tabella, ciò che si intende è il prodotto cartesiano. Ogni riga della tabella "sinistra" verrà "abbinata" (concatenata) a quella della tabella di destra.

Ora se scrivi qualcosa nella clausola where, è come mettere una condizione su questa "concatenazione" che indica quali righe "concatenare" con quali righe.

Questo è in realtà "unire" le righe :) e quindi la parola chiave join che aiuta a fornire una sintassi più leggibile ed è più comprensibile che tu voglia "davvero" aderire su alcuni valori comuni. Simile a ciò che @Dustin ha chiarito sopra.

Ora, ogni DBMS è intelligente, cioè non calcola prima il prodotto cartesiano e quindi filtra i dati (estremamente dispendiosi), ma lo fa in base alla struttura della query. L'unica cosa che mi viene in mente è che quando lo chiedi a 'join' è come rendere esplicita l'attività di join e probabilmente aiuta a far girare il codice più velocemente (di quanto? Dovrai profilarlo e vederlo) ma nel caso separato da virgola, ha bisogno di tempo per "calcolare" la strategia ottimale. Potrei sbagliarmi, ma sto solo facendo un'ipotesi su come lo si codificherà ...

    
risposta data 22.05.2011 - 12:15
fonte
4

Penso che generalmente sia meglio usare le dichiarazioni JOIN per quel caso.

Se, in futuro, si presenterà una situazione che richiede la modifica dell'istruzione da un JOINT INNER a un JOIN OUTER, questo sarà molto più facile da fare con la seconda affermazione.

    
risposta data 22.05.2011 - 03:24
fonte
2

Qualsiasi RDBMS sta per renderli la stessa cosa in termini di esecuzione. Si tratta di sapere se uno è più leggibile ed espressivo.

Usa JOIN in modo che sia chiaro quale sia la corrispondenza del join e quale sia la selezione effettiva, come in:

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

vs.

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

L'ultimo caso chiarisce immediatamente qual è la condizione di join e qual è il criterio di selezione.

    
risposta data 22.05.2011 - 03:57
fonte
1

Ho visto una volta sola i due risultati in un diverso set di ottimizzazioni e se la memoria lo serviva era in ms-sql2k su una query molto pelosa. In questo esempio, il vecchio modulo utilizzato con * = ha comportato prestazioni circa 4x più veloci. Nessuno, compresi i nostri tecnici Microsoft, potrebbe mai spiegare il perché. I ragazzi della SM l'hanno etichettato come un errore. Non l'ho mai più visto.

Poiché la maggior parte degli RDBMS è abbastanza intelligente da non fare i veri cartesiani, la ragione principale per cui posso pensare di non usarla (oltre a ciò è deprezzata) è che la maggior parte delle persone sotto i 30-35 con cui ho lavorato hanno non hai mai visto la vecchia forma prima e perdi terribilmente quando la incontrano.

    
risposta data 23.05.2011 - 21:49
fonte
-1

Il vecchio stile è stato deprecato, non dovresti usarlo.

Non dovrebbe esserci nemmeno una discussione su quale sia meglio o meno. Il nuovo codice non dovrebbe utilizzare la vecchia sintassi.

    
risposta data 23.04.2015 - 09:39
fonte
-4

Una ragione per la sintassi più concisa è che è più concisa, quindi se ti senti a tuo agio con essa è più facile da leggere. Penso al caso prolisso come simile alla scrittura di aritmetica in COBOL, ad es. MULTIPLY A BY B DONNA C.

    
risposta data 22.05.2011 - 12:42
fonte

Leggi altre domande sui tag