Вопрос

Есть ли разница в эффективности явного и неявного внутреннего соединения?Например:

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;
Это было полезно?

Решение

С точки зрения производительности они абсолютно одинаковы (по крайней мере, в SQL Server).

ПС:Имейте в виду, что IMPLICIT OUTER JOIN синтаксис устарел с версии SQL Server 2005.( IMPLICIT INNER JOIN синтаксис, используемый в вопросе, все еще поддерживается)

Устаревший синтаксис JOIN в старом стиле:Только частичная вещь

Другие советы

Лично я предпочитаю синтаксис объединения, поскольку он проясняет, что таблицы соединяются и как они соединяются.Попробуйте сравнить более крупные SQL-запросы, в которых вы выбираете из 8 разных таблиц, и у вас есть много фильтров в том месте, где.Используя синтаксис соединения, вы отделяете части, в которых таблицы соединяются, от части, в которой вы фильтруете строки.

В 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 строк.

Это очень простой случай;это никоим образом не доказывает, что оптимизатор запросов не запутается и не сгенерирует другие планы в более сложном случае.

Второй синтаксис имеет нежелательную возможность перекрестного соединения:вы можете добавлять таблицы в часть FROM без соответствующего предложения WHERE.Это считается вредным.

В первом ответе, который вы дали, используется так называемый синтаксис соединения ANSI, другой действителен и будет работать в любой реляционной базе данных.

Я согласен с Громом, что вам следует использовать синтаксис соединения ANSI.Как они сказали, основная причина – для ясности.Вместо того, чтобы использовать предложениеwhere с множеством предикатов, некоторые из которых объединяют таблицы, а другие ограничивают строки, возвращаемые с помощью синтаксиса соединения ANSI, вы даете ошеломляющую ясность, какие условия используются для соединения ваших таблиц, а какие используются для ограничения Результаты.

@lomaxx:Просто чтобы внести ясность: я почти уверен, что оба приведенных выше синтаксиса поддерживаются SQL Serv 2005.Однако приведенный ниже синтаксис НЕ поддерживается.

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

В частности, внешнее соединение (*=) не поддерживается.

С точки зрения производительности они абсолютно одинаковы (по крайней мере, в SQL Server), но имейте в виду, что этот синтаксис соединения устарел и он не поддерживается sql server2005 «из коробки».

Я думаю, вы думаете об устаревших операторах *= и =* по сравнению с.«внешнее соединение».

Я только что протестировал два приведенных формата, и они правильно работают в базе данных SQL Server 2008.В моем случае они дали идентичные планы выполнения, но я не мог с уверенностью сказать, что это всегда будет верно.

В некоторых базах данных (особенно Oracle) порядок соединений может существенно повлиять на производительность запросов (если таблиц более двух).В одном приложении у нас в некоторых случаях была разница буквально на два порядка.Использование синтаксиса внутреннего соединения дает вам контроль над этим — если вы используете правильный синтаксис подсказок.

Вы не указали, какую базу данных вы используете, но вероятность предполагает SQL Server или MySQL, где особой разницы нет.

Как заявил Ли Колдуэлл, оптимизатор запросов может создавать различные планы запросов на основе того, что функционально выглядит как один и тот же оператор SQL.Чтобы узнать больше об этом, посмотрите следующие две записи в блоге:

Одно сообщение от команды Oracle Optimizer

Еще одна запись из блога «Структурированные данные»

Надеюсь, вам это будет интересно.

С точки зрения производительности это не должно иметь никакого значения.Явный синтаксис соединения кажется мне более понятным, поскольку он четко определяет отношения между таблицами в предложении from и не загромождает предложениеwhere.

По моему опыту, использование синтаксиса перекрестного соединения с предложением-where часто приводит к нарушению плана выполнения, особенно если вы используете продукт Microsoft SQL.Например, способ, которым SQL Server пытается оценить количество строк таблицы, просто ужасен.Использование синтаксиса внутреннего соединения дает вам некоторый контроль над выполнением запроса.Итак, с практической точки зрения, учитывая атавистическую природу современной технологии баз данных, вам придется использовать внутреннее соединение.

По сути, разница между ними в том, что один написан по-старому, а другой по-современному.Лично я предпочитаю современный сценарий, использующий определения «внутренний», «левый», «внешний», «правый», потому что они более понятны и делают код более читабельным.

При работе с внутренними соединениями реальной разницы в читаемости также нет, однако при работе с левыми и правыми соединениями все может усложниться, поскольку в более старом методе вы получите что-то вроде этого:

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, в которые писали многие люди, как старшие, так и младшие.Опять же, все зависит от того, насколько читабелен сценарий и от команды, в которой вы работаете.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top