2011-03-11 15 views
7

C'è una differenza in termini di prestazioni (in mysql) traMySQL: Inner join vs Dove

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID 

E

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID 

?

+3

DUP di http://stackoverflow.com/questions/44917/explicit-vs-implicit-sql-joins – Patrick

risposta

10

Come tirato dalla risposta accettata in questione 44917:

Prestazioni saggio, che sono esattamente gli stesso (almeno in SQL Server), ma essere consapevoli che stanno deprecando il implicita outer join sintassi .

In MySql i risultati sono gli stessi.

Personalmente, vorrei aderire esplicitamente alle tabelle di join ... è il modo "socialmente accettabile" di farlo.

+0

Ho trovato la stessa risposta per Oracle, e alcuni sono d'accordo sul fatto che non c'è differenza per l'esecuzione. Per Oracle esiste un modo per ispezionare il "piano" per la query, c'è qualcosa di simile in MySQL? – Victor

+0

dipende dal tuo software. Cosa stai usando per MySql ... Toad for MySQL ha una scheda "Explain Plan" per qualsiasi query tu crei, ma probabilmente non è esattamente quello che stai cercando. Usa il comando "SPIEGARE" che Ewan menziona nella sua risposta. – Patrick

+0

Sono d'accordo che l'esplicito JOIN è migliore. In effetti, è molto più sicuro e meno incline a diventare un CROSS JOIN se si dimentica una parte della clausola WHERE. –

0

La virgola in una clausola FROM è una CROSS JOIN. Possiamo immaginare che il server SQL abbia una procedura di esecuzione di query selezionate che dovrebbe in qualche modo essere simile a questa: 1. iterare attraverso ogni tabella 2. trova le righe che soddisfano il predicato di join e inseriscile nella tabella dei risultati. 3. dalla tabella dei risultati, ottenere solo le righe che soddisfano la condizione where.

Se è davvero così, usare CROSS JOIN su una tabella con poche migliaia di righe potrebbe allocare molta memoria, quando ogni riga viene combinata l'una con l'altra prima che venga esaminata la condizione where. Il tuo server SQL potrebbe essere abbastanza occupato allora.

+0

non credo che funziona così. In tal caso, che dire se la condizione where filtra la prima tabella su un solo record, quindi combinerà solo un record con la seconda tabella, rendendolo davvero veloce? Credo che SQL gestisca i dati in altri modi (cosa che posso solo supporre). – dxvargas

0

Lo direi perché il primo esempio dice esplicitamente a mysql quali colonne aggiungere e come unirle dove il secondo mysql deve cercare di capire dove si vuole partecipare.

0

la seconda query è solo un'altra notazione per un inner join, quindi se c'è una differenza in porformance è solo perché una query può essere analizzata più velocemente dell'altro - e questa differenza, se esiste, sarà così piccola che non te ne accorgi.

Per ulteriori informazioni, si potrebbe tentare di dare un'occhiata a this question (e utilizzare la ricerca sul così la prossima volta prima di porre una domanda che è già risposto)

1

In realtà essi sono praticamente la stessa, il join/ON è syntac ANSI più recente, WHERE è la più vecchia sintassi ANSI. Entrambi sono riconosciuti dai motori di query

0

La prima query è più facile da comprendere per MySQL, quindi è probabile che il piano di esecuzione sarà migliore e che la query verrà eseguita più velocemente.

La seconda query senza la clausola where, è un cross join. Se MySQL è in grado di comprendere la clausola where abbastanza bene, farà del suo meglio per evitare di unire tutte le righe, ma non lo garantisce.

In un caso semplice come il tuo, le prestazioni saranno rigorosamente identiche.

Per quanto riguarda le prestazioni, la prima query sarà sempre migliore o identica alla seconda. E dal mio punto di vista è anche molto più facile capire quando rileggere.

10

Sono uguali.Questo può essere visto eseguendo il comando EXPLAIN:

 
mysql> explain Select * from Table1 T1 
    -> Inner Join Table2 T2 On T1.ID = T2.ID; 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra          | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
| 1 | SIMPLE  | T1 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using index         | 
| 1 | SIMPLE  | T2 | index | PRIMARY  | PRIMARY | 4  | NULL | 4 | Using where; Using index; Using join buffer | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+ 
2 rows in set (0.00 sec) 

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

Bene una risposta in ritardo da me, come sto analizzando le prestazioni di un'applicazione più vecchio che utilizza basato virgola join invece di INNER JOIN clausola.

Quindi qui ci sono due tabelle che hanno un join (entrambi hanno record più di 1 lac). Quando si esegue una query che ha un join basato su virgola, ci vuole molto più tempo rispetto al caso INNER JOIN.

Quando ho analizzato l'istruzione explain, ho trovato che la query con la virgola join utilizzava il buffer di join. Tuttavia, la query con la clausola INNER JOIN ha "utilizzato Dove".

Anche queste query sono significativamente diverse, come mostrato nella colonna righe nella query query. Queste sono le mie domande e i loro rispettivi risultati di spiegazione.

explain select count(*) FROM mbst a , his_moneypv2 b 
     WHERE b.yymm IN ('200802','200811','201001','201002','201003') 
     AND a.tel3 != '' 
     AND a.mb_no = b.mb_no 
     AND b.true_grade_class IN (3,6) 
     OR b.grade_class IN (4,7); 

+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 
| id | select_type | table | type  | possible_keys             | key         | key_len | ref | rows | Extra                | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 
| 1 | SIMPLE  | b  | index_merge | PRIMARY,mb_no,yymm,yymm_2,idx_true_grade_class,idx_grade_class | idx_true_grade_class,idx_grade_class | 5,9  | NULL | 16924 | Using sort_union(idx_true_grade_class,idx_grade_class); Using where | 
| 1 | SIMPLE  | a  | ALL   | PRIMARY              | NULL         | NULL | NULL | 134472 | Using where; Using join buffer          | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+------+--------+---------------------------------------------------------------------+ 

v/s

explain select count(*) FROM mbst a inner join his_moneypv2 b 
     on a.mb_no = b.mb_no 
     WHERE b.yymm IN ('200802','200811','201001','201002','201003') 
     AND a.tel3 != '' 
     AND b.true_grade_class IN (3,6) 
     OR b.grade_class IN (4,7); 

+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+-------+---------------------------------------------------------------------+ 
| id | select_type | table | type  | possible_keys             | key         | key_len | ref    | rows | Extra                | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+-------+---------------------------------------------------------------------+ 
| 1 | SIMPLE  | b  | index_merge | PRIMARY,mb_no,yymm,yymm_2,idx_true_grade_class,idx_grade_class | idx_true_grade_class,idx_grade_class | 5,9  | NULL    | 16924 | Using sort_union(idx_true_grade_class,idx_grade_class); Using where | 
| 1 | SIMPLE  | a  | eq_ref  | PRIMARY              | PRIMARY        | 62  | shaklee_my.b.mb_no |  1 | Using where               | 
+----+-------------+-------+-------------+----------------------------------------------------------------+--------------------------------------+---------+--------------------+------ 
+1

Dopo ulteriori analisi, ho scoperto che due vincoli sono responsabili di questa enorme differenza di prestazioni tra entrambe le query. La prima condizione di join deve essere prima nella clausola where prima di qualsiasi altra condizione del filtro. Seconda parentesi con istruzioni gruppo che hanno o –

+0

Le query non restituiscono le stesse righe. Le righe di unione incrociata con 'b.grade_class IN (4,7)' sono sempre nell'output dal primo 'from', ma quando' a.mb_no = b.mb_no' non sono nell'output dal secondo 'from' . Quindi confrontare le query non ti dice nulla sulla domanda. – philipxy