Явное vs неявное объединение SQL
Есть ли разница в эффективности в явном vs неявном внутреннем соединении?
Например:
SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;
против.
SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;
Ответы
Ответ 1
Производительность, они одинаковы (по крайней мере, в SQL Server).
PS: Имейте в виду, что синтаксис IMPLICIT OUTER JOIN
устарел после SQL Server 2005. (Синтаксис IMPLICIT INNER JOIN
, используемый в вопросе, по-прежнему поддерживается)
Устаревание "старого стиля" JOIN Синтаксис: только частичная вещь
Ответ 2
Лично я предпочитаю синтаксис соединения, так как он дает понять, что таблицы объединены и как они объединены. Попробуйте сравнить более крупные SQL-запросы, в которых вы выбираете из 8 разных таблиц, и у вас много фильтрации в том месте. Используя синтаксис соединения, вы выделяете части, в которых соединяются таблицы, с той частью, где вы фильтруете строки.
Ответ 3
В MySQL 5.1.51 оба запроса имеют одинаковые планы выполнения:
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
имеет 166208 строк; table2
имеет около 1000 строк.
Это очень простой случай; это никоим образом не доказывает, что оптимизатор запросов не запутался и не сгенерировал разные планы в более сложном случае.
Ответ 4
Второй синтаксис имеет нежелательную возможность перекрестного соединения: вы можете добавлять таблицы в часть FROM без соответствующего предложения WHERE. Это считается вредным.
Ответ 5
Первый ответ, который вы дали, использует то, что известно как синтаксис объединения ANSI, другой действителен и будет работать в любой реляционной базе данных.
Я согласен с grom, что вы должны использовать синтаксис ANSI join. По их словам, главная причина заключается в ясности. Вместо того, чтобы иметь предложение where с множеством предикатов, некоторые из которых объединяют таблицы и другие, ограничивающие строки, возвращаемые синтаксисом ANSI join, вы делаете его ослепительно понятным, какие условия используются для соединения ваших таблиц и которые используются для ограничения результаты.
Ответ 6
@lomaxx: просто для уточнения, я вполне уверен, что оба синтаксиса поддерживаются SQL Serv 2005. Синтаксис ниже НЕ поддерживается, однако
select a.*, b.*
from table a, table b
where a.id *= b.id;
В частности, внешнее соединение (* =) не поддерживается.
Ответ 7
Производительность по-разному, они абсолютно одинаковы (по крайней мере, в SQL Server), но имейте в виду, что они умаляют этот синтаксис соединения и не поддерживаются sql server2005 из коробки.
Я думаю, вы думаете об устаревших операторах * = и = * против "внешнего соединения".
Я только что протестировал два указанных формата, и они работают правильно в базе данных SQL Server 2008. В моем случае они дали одинаковые планы выполнения, но я не мог уверенно сказать, что это всегда будет правдой.
Ответ 8
В некоторых базах данных (в частности, Oracle) порядок соединений может существенно повлиять на производительность запросов (если имеется более двух таблиц). В одном случае в некоторых случаях мы имели разницу на два порядка. Использование синтаксиса внутреннего соединения дает вам контроль над этим - если вы используете синтаксис правильных подсказок.
Вы не указали, какую базу данных вы используете, но вероятность предполагает SQL Server или MySQL, где это не имеет никакого значения.
Ответ 9
Как заявил Leigh Caldwell, оптимизатор запросов может создавать разные планы запросов на основе того, что функционально выглядит как тот же оператор SQL. Для дальнейшего ознакомления с этим взгляните на следующие два блога: -
Одно сообщение из команды Oracle Optimizer
Другая публикация из блога "Структурированные данные"
Надеюсь, вы найдете это интересным.
Ответ 10
Эффективность, она не должна иметь никакого значения. Явный синтаксис соединения кажется мне более чистым, поскольку он четко определяет отношения между таблицами в предложении from и не загромождает предложение where.
Ответ 11
По моему опыту, использование синтаксиса cross-join-a-where-clause часто приводит к плану выполнения работы с повреждением мозга, особенно если вы используете продукт Microsoft SQL. То, как SQL Server пытается оценить количество строк таблицы, например, ужасно ужасно. Использование синтаксиса внутреннего соединения дает вам некоторый контроль над тем, как выполняется запрос. Итак, с практической точки зрения, учитывая атавистический характер современной технологии баз данных, вы должны пойти с внутренним соединением.
Ответ 12
По сути, разница между ними заключается в том, что один написан по-старому, а другой написан по-современному. Лично я предпочитаю современный скрипт, использующий внутреннее, левое, внешнее и правое определения, потому что они более понятны и делают код более читабельным.
При работе с внутренними объединениями нет никакой реальной разницы в удобочитаемости, однако это может усложниться при работе с левым и правым объединениями, поскольку в более старом методе вы получите что-то вроде этого:
SELECT *
FROM table a, table b
WHERE a.id = b.id (+);
Выше приведен старый способ написания левого соединения, в отличие от следующего:
SELECT *
FROM table a
LEFT JOIN table b ON a.id = b.id;
Как вы можете видеть визуально, современный способ написания скрипта делает запрос более читабельным. (Кстати, то же самое касается правильных объединений и немного более сложного для внешних объединений).
Возвращаясь к основной теме, для компилятора SQL не имеет значения, как написан запрос, поскольку он обрабатывает их одинаково. Я видел смесь обоих в базах данных Oracle, в которые записывалось много людей, как старших, так и младших. Опять же, все сводится к тому, насколько читаем сценарий и команда, с которой вы работаете.