2009-03-22 16 views
45

L'effetto dell'emissione di un'unione interna equivale a indicare un cross join con la condizione di join nella clausola WHERE. Ho notato che molte persone nella mia azienda usano i cross join, dove utilizzerei i join interni. Non ho notato alcun significativo aumento delle prestazioni dopo aver modificato alcune di queste query e mi chiedevo se fosse solo una coincidenza o se il DBMS ottimizza tali problemi in modo trasparente (MySql nel nostro caso). Ed ecco un esempio concreto per la discussione:Prestazioni dell'aggregazione interna rispetto all'aggiunta incrociata

SELECT User.* 
FROM User, Address 
WHERE User.addressId = Address.id; 

SELECT User.* 
FROM User 
INNER JOIN Address ON (User.addressId = Address.id); 
+6

Il primo non è ANSI SQL. So che Microsoft ha raccomandato di passare alla sintassi del secondo esempio. MySQL può fare lo stesso ora che sono aziendali. Inoltre, il primo non è un cross join. Un cross join verrebbe se si dimenticasse la clausola where. – WakeUpScreaming

+2

Perché non è ANSI SQL? – soulmerge

+4

Quello che si chiama cross join è una sintassi più vecchia. Noi dinosauri :) tendiamo a usarlo. La sintassi Inner join è stata concordata come parte dello standard SQL 92 (IIRC). Da allora i venditori si sono mossi verso il supporto di esso con la maggior parte dei fornitori che supportano entrambi. Pertanto non è ANSI perché non è presente nei documenti. – Karl

risposta

43

I join incrociati producono risultati costituiti da ogni combinazione di righe da due o più tabelle. Ciò significa che se la tabella A ha 6 righe e la tabella B ha 3 righe, una croce produrrà 18 righe. Non esiste una relazione stabilita tra i due tavoli: si produce letteralmente ogni combinazione possibile.

Con un join interno, i valori di colonna di una riga di una tabella vengono combinati con i valori di colonna di un'altra riga di un'altra (o la stessa) tabella per formare una singola riga di dati.

Se una clausola WHERE viene aggiunta a un cross join, si comporta come un inner join poiché WHERE impone un fattore limitante.

Fintanto che le vostre richieste rispettano il buon senso e lo specifico performance guidelines del fornitore, mi piace pensare alla decisione su quale tipo di join utilizzare per essere una semplice questione di gusto.

14

Usa EXPLAIN per visualizzare il piano di query per entrambe le query, e vedere se c'è qualche differenza. Molto probabilmente MySQL utilizzerà lo stesso piano di esecuzione in entrambi i casi. Io uso la sintassi INNER JOIN principalmente perché è molto più chiara.

23

Non c'è altra differenza che l'inner join è molto più chiaro perché definisce il join, lasciando che la clausola where sia l'effettiva condizione di limitazione.

1

L'ordine in cui ti unisci alle tabelle o le condizioni ON/WHERE non dovrebbero avere importanza.

Query Optimizer deve ottimizzare e utilizzare il miglior ordine in ogni caso (e scegliendo come filtrare meglio i dati, da dove cominciare, ecc)

Come molti altri, però, vi consiglio di usare la sintassi INNER JOIN, dal momento che rende le cose molto più leggibili, è più trasparente anche con la sintassi dei join LEFT o FULL.

C'è un testo un po 'più su di esso dimora qui: http://linus.brimstedt.se/?/article/articleview/SQL Sintassi

/B

2

Il primo esempio è funzionalmente uguale al secondo esempio. Tuttavia, questa sintassi dovrebbe essere evitata per diversi motivi. Innanzitutto è molto più facile ottenere accidentalmente un cross join quando si utilizza questa sintassi, specialmente quando ci sono più join nella tabella. Se vedi molto questo tipo di query con la parola chiave distinta, probabilmente hai qualcuno che sta provando a correggere i cross join.

Successivamente, la sintassi di join sinistra e destra utilizzando lo stile precedente è obsoleta e non sarà più supportata. Inoltre, non funziona correttamente ora comunque. Talvolta interpreta erroneamente l'unione esterna e restituisce i risultati errati impostati. Quindi tutte le domande che hai utilizzato = o = nella clausola where devono essere immediatamente sostituite.

In terzo luogo, i join standard ANSI sono più facili da comprendere e gestire.Una conoscenza dei join è una delle competenze di base più critiche di cui chiunque abbia bisogno di interrogare qualsiasi database relazionale. È stata la mia esperienza che alcune persone che usano lo stile precedente non capiscono veramente i join e il modo in cui funzionano e quindi scrivono query che in realtà non fanno ciò che intendevano.

10

Trovo che i luoghi di lavoro che consentono la prima sintassi (tabelle separate da virgola) tendano ad avere tempi significativi di debug dei casi in cui vengono restituite più righe del previsto. I cross incrociati involontari sono la rovina di un sistema e possono portare anche il database più ben sintonizzato alle sue ginocchia. Ha portato il nostro sistema di pre-produzione a una brusca frenata in almeno due occasioni nell'ultimo anno.

La seconda sintassi (sintassi di join) obbliga lo scrittore a pensare a come le tabelle vengono prima unite, quindi restituiscono solo le righe interessanti. È impossibile eseguire accidentalmente un cross join usando questa sintassi, e quindi il rischio di query accidentali poco performanti viene ridotto.

Tuttavia, a parte questo problema, non ho mai notato alcuna differenza di velocità tra le due sintassi in tutti i sistemi che ho avuto.

1

Un ulteriore vantaggio della prima sintassi è che si può essere più generici nella condizione di limitazione. Non solo l'uguaglianza.

Ma se si utilizza l'uguaglianza, perché fidarsi dell'ottimizzatore? Assicurati che non genererà prima il cross join e quindi eliminerà le righe. Usa il secondo.

+0

Potrebbe essere vero per MySQL, non lo so. Ma in SQL Server, puoi mettere altre condizioni rispetto all'uguaglianza sul lato destro del "on". –

+0

Puoi fare lo stesso in MySQL. –

-1

Fin dall'inizio, gli ottimizzatori si sono sviluppati attorno alla classica sintassi dei prodotti cartesiani a restrizione dei progetti. Praticamente tutti i fornitori hanno copiato il progetto lanciato da System R. Poi, a malincuore, i venditori hanno adottato la "più recente e migliore" sintassi ANSI e hanno riadattato i loro motori di esecuzione SQL. Contrariamente a ciò che può essere indicato nella brochure di marketing ("usa la sintassi più recente"), non è stato cambiato molto sul livello di implementazione fisica: è ancora [indicizzato] loop annidati, o hash o join di unione. Pertanto, non vi è alcuna base per assumere la superiorità di una sintassi rispetto all'altra.

A mio gusto personale, la nuova sintassi è redundant, rumorosa e inconsistent. Per essere sanzionato dal comitato, "entra in ogni parco in ogni città e non troverai statue di commissione".

+0

L'uso di join impliciti è un antipattern SQL. È soggetto a cross join accidentali, è più difficile da mantenere soprattutto se è necessario passare a join esterni ad un certo punto (non si deve mescolare i due e la sintassi implicita di outer join almeno in alcuni database non funziona comunque correttamente). Se in realtà vuoi un cross join non c'è modo di sapere se è vero o se si soffre del problema di cross join accidentale. Quindi l'intento non è chiaro. Questa è solo una cattiva pratica. – HLGEM

0

Spiegazione entrambe le query dà stessa uscita

mysql> explain select * from t T1, t T2 where T1.ID=T2.ID; 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| 1 | SIMPLE  | T1 | ALL | PRIMARY  | NULL | NULL | NULL | 3 |        | 
| 1 | SIMPLE  | T2 | ALL | PRIMARY  | NULL | NULL | NULL | 3 | Using where; Using join buffer | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
2 rows in set (0.00 sec) 

mysql> explain select * from t T1 join t T2 on T1.ID=T2.ID; 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra       | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
| 1 | SIMPLE  | T1 | ALL | PRIMARY  | NULL | NULL | NULL | 3 |        | 
| 1 | SIMPLE  | T2 | ALL | PRIMARY  | NULL | NULL | NULL | 3 | Using where; Using join buffer | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+ 
2 rows in set (0.00 sec) 

Ma usando join interno sintassi è preferibile perché è più chiara e più precisa. Mysql può sincronizzare internamente le query di join Left e Right per selezionare meno dati rispetto a Cross Join.

Problemi correlati