Явно против неявного соединения SQL

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

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;

11 ответов


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

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

устаревание синтаксиса соединения" старого стиля": только частичная вещь


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


на 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 join, другой действителен и будет работать в любой реляционной базе данных.

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


@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.


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