Внутреннее соединение против Где

Есть ли разница в производительности (в оракуле) между

Select * from Table1 T1 Inner Join Table2 T2 On T1.ID = T2.ID 

А также

 Select * from Table1 T1, Table2 T2 Where T1.ID = T2.ID 

?

Нет! Тот же план выполнения, посмотрите на эти две таблицы:

 CREATE TABLE table1 ( id INT, name VARCHAR(20) ); CREATE TABLE table2 ( id INT, name VARCHAR(20) ); 

План выполнения запроса с использованием внутреннего соединения:

 -- with inner join EXPLAIN PLAN FOR SELECT * FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.id; SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY); -- 0 select statement -- 1 hash join (access("T1"."ID"="T2"."ID")) -- 2 table access full table1 -- 3 table access full table2 

И план выполнения запроса с использованием предложения WHERE.

 -- with where clause EXPLAIN PLAN FOR SELECT * FROM table1 t1, table2 t2 WHERE t1.id = t2.id; SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY); -- 0 select statement -- 1 hash join (access("T1"."ID"="T2"."ID")) -- 2 table access full table1 -- 3 table access full table2 

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

Они должны быть точно такими же. Однако, как практика кодирования, я бы предпочел увидеть Join. Он четко формулирует ваши намерения,

Использование JOIN упрощает чтение кода, поскольку оно самоочевидно.

Нет никакой разницы в скорости ( я только что протестировал ее ), и план выполнения тот же.

Я не знаю об Oracle, но я знаю, что старый синтаксис устарел в SQL Server и в конце концов исчезнет. Прежде чем использовать этот старый синтаксис в новом запросе, я бы уточнил, что Oracle планирует с ним делать.

Я предпочитаю более новый синтаксис, а не смешивание критериев соединения с другими необходимыми условиями. В более новом синтаксисе гораздо яснее, что создает соединение и какие другие условия применяются. Не очень большая проблема в коротком запросе, подобном этому, но он становится намного более запутанным, когда у вас есть более сложный запрос. Поскольку люди учатся по основным запросам, я бы предпочел, чтобы люди научились использовать синтаксис соединения до того, как они нуждаются в этом в сложном запросе.

И еще раз я не знаю Oracle специально, но я знаю, что версия SQL Server старого стиля в левом членстве ошибочна даже в SQL Server 2000 и дает непоследовательные результаты (иногда левое соединение иногда перекрестное соединение), поэтому оно никогда не должно быть используемый. Надеюсь, Oracle не пострадает от одной и той же проблемы, но, конечно, левое и правое объединение может быть сложнее, чем правильно выразить в старом синтаксисе.

Кроме того, это был мой опыт (и, конечно же, это личное мнение, у вас может быть отличный опыт), что разработчики, использующие стандартные стандарты ANSII, имеют тенденцию лучше понимать, что такое соединение, и что это означает с точки зрения получения данные из базы данных. Я верю в то, что большинство людей с хорошим пониманием базы данных склонны писать более сложные запросы, и мне кажется, что их гораздо проще поддерживать, используя стандарт ANSII, чем старый стиль.

Они логически идентичны, но в более ранних версиях Oracle, которые применяли синтаксис ANSI, с ними часто возникали ошибки в более сложных случаях, поэтому иногда вы сталкиваетесь с сопротивлением разработчиков Oracle при его использовании.

[Для бонусной точки …]

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

Как и все остальные, они функционально одинаковы, однако JOIN более четко заявляет о намерениях. Поэтому он может помочь оптимизатору запросов в текущих версиях oracle в некоторых случаях (я не знаю, если это так), это может помочь оптимизатору запросов в будущих версиях Oracle (никто не имеет идеи), или он может помочь, если вы меняете поставщика базы данных.

Производительность должна быть одинаковой, но я бы предложил использовать версию join из-за большей ясности, когда речь заходит о внешних соединениях.

Также можно избежать непреднамеренных декартовых продуктов, используя версию join.

Третий эффект – это легче читать SQL с более простым WHERE-условием.

Не забывайте, что в Oracle, если атрибуты ключа соединения называются одинаковыми в обеих таблицах, вы также можете записать это как:

 select * from Table1 inner join Table2 using (ID); 

Конечно, у этого тоже есть тот же план запросов.

В PostgreSQL нет никакой разницы – они оба приравниваются к одному и тому же тарифному плану. Я на 99% уверен, что это также относится к Oracle.

В сценарии, где таблицы находятся в 3-й нормальной форме, объединения между таблицами не должны меняться. Т.е. присоединяйтесь к КЛИЕНТАМ, и ПЛАТЕЖИ всегда должны оставаться прежними.

Однако мы должны отличать соединения от фильтров . Соединения связаны с отношениями и фильтрами – это разделение целого.

Синтаксис SQL-92 побуждает нас разделять обе концепции и предпочитает более старый синтаксис, который ставит оба, объединения и фильтры в предложение WHERE, которое является более громоздким.

Функционально они такие же, как было сказано. Я согласен с тем, что сделать соединение лучше для описания того, что вы хотите сделать. Много раз я думал, что знаю, как я хотел что-то запросить до тех пор, пока я не начал делать присоединения, и понял, что хочу сделать другой запрос, чем оригинальный в моей голове.

Они оба являются внутренними объединениями, которые делают одно и то же, просто используют новый синтаксис ANSI.

Верно, что функционально оба запроса должны обрабатываться одинаково. Однако опыт показывает, что если вы выбираете из представлений, которые используют новый синтаксис соединения, важно также структурировать ваши запросы, используя его. Оптимизатор Oracle может запутаться, если представление использует оператор «join», но запрос, обращенный к представлению, использует традиционный метод соединения в предложении «where».

Хотя идентичность двух запросов кажется очевидной, иногда случаются некоторые странные вещи. Я пришел с запросом, у которого есть разные планы выполнения при перемещении предиката соединения из JOIN в WHERE в Oracle 10g (для плана WHERE лучше), но я не могу воспроизвести эту проблему в упрощенных таблицах и данных. Я думаю, это зависит от моих данных и статистики. Оптимизатор – довольно сложный модуль, и иногда он ведет себя волшебным образом.

Вот почему мы не можем ответить на этот вопрос вообще, потому что это зависит от внутренних компонентов БД. Но мы должны знать, что ответ должен быть « без различий ».

У меня была эта головоломка сегодня, когда мы проверяли время выпуска нашего sp's на производстве, изменили внутреннее соединение на столе, построенном из XML-корма, на предложение «где». … среднее время выполнения теперь составляет 80 мс за 1000 исполнений, тогда как до среднего exec было 2,2 секунды … существенная разница в плане выполнения – это исчезновение ключевого поиска … Сообщение, которое вы не знаете до тех пор, пока не проверите оба метода.

веселит.

Они оба объединяются, и где они делают то же самое.

Посмотрите на запросы MySQL, зачем использовать соединение вместо того, где?

Как сказал kiewik, план исполнения тот же.

Заявление JOIN читается более легко, что упрощает не забывать условие ON и получать декартовую продукцию. Эти ошибки могут быть довольно сложными для обнаружения в длинных запросах с использованием нескольких объединений типа: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Если вы забудете только одно условие соединения, вы получите очень длинный запрос, возвращающий слишком много записей … на самом деле слишком много. Некоторые poeple используют DISTINCT для исправления запроса, но выполнить его еще очень долго.

Именно поэтому использование инструкции JOIN – это, безусловно, лучшая практика: улучшенная ремонтопригодность и удобство чтения.

Более того, если я хорошо помню, JOIN оптимизирован относительно использования памяти.