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

197

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

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

и

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

?

  • 1
    только для записи, я видел, что запросы возвращают разные результаты только при переходе от предложения where к предложению where
  • 10
    @ BlackTigerX: разные результаты? Были ли какие-либо внешние соединения? Потому что я не вижу, как будут отличаться результаты между inner join ... on сопоставлением эквивалентных критериев объединения в предложении where .
Показать ещё 3 комментария
Теги:
performance

18 ответов

176
Лучший ответ

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

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
  • 4
    Я действительно хочу посмотреть, есть ли официальная документация от Oracle об этом
64

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

  • 21
    Да, производительность должна быть такой же. Но синтаксис SELECT * FROM Table1, Table2 WHERE ... ЗЛО!
  • 2
    Я считаю, что гораздо проще понять для внутренних соединений, чем синтаксис SQL-92. Ваш пробег может отличаться.
Показать ещё 4 комментария
51

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

  • 7
    Согласен. Особенно, если вы присоединяетесь к нескольким таблицам, намного проще проанализировать оператор выбора, если вы делаете явные объединения.
  • 10
    В самом деле. Объединения представляют собой семантические отношения между двумя наборами данных, но где предлагается отфильтрованный набор. +1
23

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

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

  • 0
    Спасибо. я искал скорость сжатия между этими двумя методами.
15

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

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

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

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

  • 1
    Аминь, брат. Долой СОЕДИНИТЕЛЕЙ !!
13

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

  • 0
    Более ранние версии Oracle имели ошибки с этим? Как рано? Какая версия (ы)?
  • 0
    У Металинка есть детали ... они всплывают повсюду.
12

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

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

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

  • 2
    Или ... легко измените ВНУТРЕННИЕ СОЕДИНЕНИЯ на ЛЕВЫЕ СОЕДИНЕНИЯ, чтобы вы увидели, какое соединение вызывает пропуск ожидаемых строк. Я делаю это, потому что я делаю весь запрос одновременно. Если вы прокомментируете INNER JOINS, вы должны выполнить процесс исключения. Это займет больше времени. Но +1 для вас, потому что это одна из моих любимых причин для ВНУТРЕННИХ СОЕДИНЕНИЙ кроме читабельности!
7

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

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

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

  • 0
    Я действительно думаю, что ключ к непреднамеренным последствиям, когда критерии неоднозначны. Если вы указываете тип объединения, вы точно знаете, что вы получаете. Я обнаружил, что разные базы данных и даже разные версии одной и той же платформы баз данных будут по-разному обрабатывать нулевые значения в подразумеваемом соединении. Когда вы указываете левый / правый внутренний / внешний, вы тратите время на обдумывание того, что является правильным. Когда вы используете неоднозначный метод, вы предполагаете, что он работает так, как вы надеетесь / намереваетесь.
6

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

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

У этого также есть тот же план запроса, конечно.

  • 0
    Я откатил издание, потому что предыдущая редакция изменила смысл ответа
3

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

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

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

3

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

2

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

1

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

  • 0
    Это больше проблема с представлениями, чем с соединениями вообще.
1

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

0

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

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

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

Точно, почему использование JOIN-инструкции, безусловно, является лучшей практикой: лучшей ремонтопригодностью и лучшей читабельностью.

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

0

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

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

0

У меня была эта головоломка сегодня, когда мы проверяли одно из наших сроков выпуска в производство, изменили внутреннее соединение на столе, построенном из XML-корма, на предложение "where" вместо этого.... среднее время выполнения теперь составляет 80 мс за 1000 казни, тогда как до среднего exec было 2,2 секунды... существенная разница в плане выполнения - это исчезновение ключевого поиска... Сообщение, которое вы не знаете, пока не проведете тестирование с использованием обоих методов.

приветствий.

0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню