Explicit vs implicit SQL joins

Czy jest jakaś różnica wydajności w jawnym vs ukrytym połączeniu wewnętrznym? Na przykład:

SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;

Vs.

SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;
 333
Author: user8839064, 2008-09-05

11 answers

Pod względem wydajności, są dokładnie takie same (przynajmniej w SQL serverze).

PS: należy pamiętać, że składnia IMPLICIT OUTER JOIN jest przestarzała od SQL Server 2005. (Składnia IMPLICIT INNER JOIN używana w pytaniu jest nadal obsługiwana)

Składnia" Old Style " JOIN: Only a Partial Thing

 112
Author: lomaxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 16:11:42

Osobiście preferuję składnię join, ponieważ sprawia, że jaśniej jest, że tabele są połączone i jak są połączone. Spróbuj porównać większe zapytania SQL gdzie wybierając z 8 różnych tabel i masz dużo filtrowania w gdzie. Używając składni join oddzielisz części, w których połączone są tabele, od części, w której filtrowane są wiersze.

 117
Author: grom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 23:23:25

W MySQL 5.1.51 oba zapytania mają identyczne plany wykonania:

mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.02 sec)

mysql> explain select * from table1 a, table2 b where a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.00 sec)

table1 ma 166208 wierszy; table2 ma około 1000 wierszy.

Jest to bardzo prosty przypadek; w żaden sposób nie dowodzi, że optymalizator zapytań nie pomyliłby się i nie wygenerowałby różnych planów w bardziej skomplikowanym przypadku.

 41
Author: Matt Fenwick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 01:43:26

Druga składnia ma niechcianą możliwość łączenia krzyżowego: możesz dodawać tabele do części FROM bez odpowiadającej klauzuli WHERE. Jest to uważane za szkodliwe.

 33
Author: edosoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-12 16:59:46

Pierwsza odpowiedź, którą podałeś, używa składni ANSI join, druga jest poprawna i będzie działać w dowolnej relacyjnej bazie danych.

Zgadzam się z grom, że należy używać składni ANSI join. Jak powiedzieli, głównym powodem jest jasność. Zamiast mieć klauzulę where z dużą ilością predykatów, z których niektóre join tables i inne ograniczające wiersze zwracane za pomocą składni ANSI join, robisz ślepo jasne, Które warunki są używane do łączenia tabel i które są wykorzystywane w celu ograniczenia wyników.

 14
Author: andy47,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-07 09:55:30

@lomaxx: tak dla jasności, jestem całkiem pewien, że obie powyższe składnie są obsługiwane przez SQL Serv 2005. Poniższa składnia nie jest jednak obsługiwana

select a.*, b.*  
from table a, table b  
where a.id *= b.id;

W szczególności złącze zewnętrzne (*=) nie jest obsługiwane.

 6
Author: deadbug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-28 13:35:08

Pod względem wydajności, są one dokładnie takie same (przynajmniej w SQL Server), ale należy pamiętać, że dezaktualizują składnię join i nie jest ona obsługiwana przez SQL server2005 po wyjęciu z pudełka.

Myślę, że myślisz o przestarzałych operatorach * = i = * kontra "zewnętrzne połączenie".

Właśnie przetestowałem dwa podane formaty i działają poprawnie na bazie danych SQL Server 2008. W moim przypadku przyniosły identyczne plany egzekucji, ale nie mogłem śmiało powiedzieć, że to to zawsze będzie prawda.

 4
Author: Joshdan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 23:33:25

W niektórych bazach danych (zwłaszcza Oracle) kolejność połączeń może mieć ogromne znaczenie dla wydajności zapytań (jeśli jest więcej niż dwie tabele). Na jednym wniosku, mieliśmy dosłownie dwa rzędy wielkości różnicy w niektórych przypadkach. Użycie składni INNER join daje Ci kontrolę nad tym - jeśli używasz właściwej składni podpowiedzi.

Nie określiłeś, której bazy danych używasz, ale prawdopodobieństwo sugeruje, że SQL Server lub MySQL tam, gdzie nie ma to żadnej różnicy.

 2
Author: Leigh Caldwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 23:38:08

Jak stwierdził Leigh Caldwell, optymalizator zapytań może tworzyć różne plany zapytań w oparciu o to, co funkcjonalnie wygląda jak ta sama instrukcja SQL. Aby dowiedzieć się więcej na ten temat, zajrzyj do następujących dwóch wpisów na blogu: -

Jeden post od zespołu Oracle Optimizer

Kolejny wpis z bloga "Structured Data"

Mam nadzieję, że to cię zainteresuje.

 1
Author: Mike McAllister,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 17:44:01

Wydajność nie powinna mieć znaczenia. Jawna składnia join wydaje mi się czystsza, ponieważ jasno definiuje relacje między tabelami w klauzuli from i nie zaśmieca klauzuli where.

 1
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-30 18:30:32

Z mojego doświadczenia wynika, że używanie składni cross-join-with-a-WHERE-clause często powoduje uszkodzenie mózgu, zwłaszcza jeśli używasz produktu Microsoft SQL. Sposób, w jaki na przykład SQL Server próbuje oszacować liczbę wierszy tabeli, jest okrutnie okropny. Użycie składni INNER join daje pewną kontrolę nad tym, jak zapytanie jest wykonywane. Tak więc z praktycznego punktu widzenia, biorąc pod uwagę atawistyczny charakter obecnej technologii bazodanowej, musisz przejść z wewnętrznym połączeniem.

 0
Author: Sean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 18:09:17