Явные и неявные 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;
1003   11  

11 ответов:

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

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

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

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

на 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.

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

Comments

    Ничего не найдено.