Есть ли разница в производительности (в оракуле) между
Select * from Table1 T1
Inner Join Table2 T2 On T1.ID = T2.ID
И
Select * from Table1 T1, Table2 T2
Where T1.ID = T2.ID
?
@BlackTigerX: разные результаты? Были ли задействованы какие-либо внешние соединения? Потому что я не понимаю, насколько разные результаты будут иметь место между inner join ... on и эквивалентными критериями соединения в предложении where.
в старой версии базы данных Oracle не существует join
@MajidTaheri: о какой старее версии Oracle вы говорите? Любая версия, поддерживаемая Oracle, поддерживает нотацию JOIN.
Ищите общие ответы или лучшие практики, основанные на тривиальных случаях. Хотелось бы увидеть «повторное сопоставление» с более сложными предложениями where, включающими несколько условий AND. По крайней мере, с SQL Server есть точка пересечения.
Здесь следует отметить одну вещь: если вы используете inner join и пропустите предложение on, это приведет к ошибке. Однако, если вы пропустите раздел where в ,, он вместо этого вернет перекрестное соединение!


Если оптимизатор запросов выполняет свою работу правильно, между этими запросами не должно быть разницы. Это всего лишь два способа указать один и тот же желаемый результат.
Да, производительность должна быть такой же. Но синтаксис SELECT * FROM Table1, Table2 WHERE ... ЗЛО!
Мне гораздо легче понять FOR INNER JOINS, чем синтаксис SQL-92. Ваш пробег может отличаться.
Я считаю, что синтаксис WHERE легче читать, чем INNER JOIN - я думаю, это похоже на Vegemite. Большинство людей в мире, вероятно, находят его отвратительным, но дети, выросшие на его еде, любят его.
Vegemite действительно противный, но опять же, я люблю лом. Иди разберись.
Сначала я выучил JOIN, но после того, как я открыл для себя multi-from, я обнаружил, что их намного легче запоминать, читать и использовать. Что это меня делает?
Просто любопытно, почему люди предпочитают синтаксис JOIN. Легче читать? Более явное различие между объединением и фильтрацией? Лично я считаю, что JOINs Сильнее читать не легче.
@Darryl Я думаю, что JOIN легче читать, потому что условие объединения таблиц определяется прямо здесь, а не «где-то» в предложении WHERE. Я предпочитаю зарезервировать предложение WHERE для ограничения набора данных (например, WHERE DATE > (SYSDATE - 1)) вместо того, чтобы также определять, как таблицы связаны друг с другом (например, WHERE T1.ID = T2.ID). Для небольшой таблицы, подобной рассматриваемому примеру, разница невелика, но для больших запросов, включающих несколько таблиц и несколько условий, я думаю, что это значительно упрощает понимание запроса.
В PostgreSQL определенно нет разницы - они оба соответствуют одному и тому же плану запроса. Я на 99% уверен, что это относится и к Oracle.
Они должны быть точно такими же. Однако в качестве практики кодирования я бы предпочел присоединиться. Он четко формулирует ваши намерения,
Я согласен. Особенно, если вы присоединяетесь к нескольким таблицам, гораздо проще проанализировать оператор select, если вы выполняете явное присоединение.
Верно. Объединения представляют собой семантическую связь между двумя наборами данных, но где предлагает отфильтрованный набор. +1
Они оба являются внутренними объединениями, которые делают одно и то же, один просто использует новый синтаксис ANSI.
Функционально они такие же, как было сказано. Я согласен, однако, что выполнение соединения лучше для точного описания того, что вы хотите сделать. Много раз мне казалось, что я знаю, как я хочу что-то запросить, пока я не начал выполнять соединения и не понял, что хочу выполнить другой запрос, чем исходный запрос в моей голове.
Они логически идентичны, но в более ранних версиях Oracle, которые использовали синтаксис ANSI, часто возникали ошибки в более сложных случаях, поэтому вы иногда столкнетесь с сопротивлением со стороны разработчиков Oracle при его использовании.
В более ранних версиях Oracle были ошибки с этим? Как рано? Какие версии?
У Metalink есть подробности ... они всплывают повсюду.
Я не знаю об Oracle, но знаю, что старый синтаксис в SQL Server устарел и со временем исчезнет. Прежде чем использовать этот старый синтаксис в новом запросе, я хотел бы проверить, что Oracle планирует с ним делать.
Я предпочитаю новый синтаксис, а не смешивание критериев соединения с другими необходимыми условиями where. В новом синтаксисе гораздо яснее, что создает соединение и какие другие условия применяются. На самом деле это не большая проблема в таком коротком запросе, но гораздо больше сбивает с толку, когда у вас есть более сложный запрос. Поскольку люди учатся на базовых запросах, я бы предпочел, чтобы люди научились использовать синтаксис соединения, прежде чем он им понадобится в сложном запросе.
И снова я не знаю конкретно Oracle, но я знаю, что версия SQL Server старого стиля левого соединения ошибочна даже в SQL Server 2000 и дает несогласованные результаты (иногда левое соединение, иногда перекрестное соединение), поэтому оно никогда не должно быть использовал. Надеюсь, Oracle не страдает той же проблемой, но определенно левое и правое объединение может быть намного сложнее правильно выразить в старом синтаксисе.
Кроме того, по моему опыту (и, конечно, это строго личное мнение, у вас может быть другой опыт), разработчики, использующие стандартные объединения ANSII, как правило, лучше понимают, что такое объединение и что оно означает с точки зрения получения данные из базы данных. Я полагаю, что это связано с тем, что большинство людей с хорошим пониманием базы данных склонны писать более сложные запросы, и мне кажется, что их намного проще поддерживать с использованием стандарта ANSII, чем старый стиль.
Аминь, брат. Долой СОЕДИНЕНИЙ !!
Использование JOIN упрощает чтение кода, поскольку он не требует пояснений.
Нет разницы в скорости (Я только что проверил это) и план выполнения такой же.
Спасибо. я искал сжатие скорости между этими двумя методами.
Верно, что функционально оба запроса должны обрабатываться одинаково. Однако опыт показал, что если вы выбираете из представлений, использующих новый синтаксис соединения, важно также структурировать свои запросы с его использованием. Оптимизатор Oracle может запутаться, если представление использует оператор "join", но запрос, обращающийся к представлению, использует традиционный метод объединения в предложении "where".
Это больше проблема с представлениями, чем с соединениями вообще.
Производительность должна быть идентичной, но я бы предложил использовать версию соединения из-за большей ясности, когда дело доходит до внешних соединений.
Также можно избежать непреднамеренных декартовых произведений, используя версию соединения.
Третий эффект - облегчение чтения SQL с более простым условием WHERE.
Я действительно думаю, что ключ кроется в непреднамеренных эффектах, когда критерии неоднозначны. Если вы укажете тип соединения, вы точно знаете, что получаете. Я обнаружил, что разные базы данных и даже разные версии одной и той же платформы базы данных по-разному обрабатывают нулевые значения в подразумеваемом соединении. Когда вы указываете левое / правое внутреннее / внешнее, вы тратите время на размышления о том, что является правильным. Когда вы используете неоднозначный метод, вы предполагаете, что он работает так, как вы надеетесь / намереваетесь.
Нет! Тот же план выполнения, посмотрите на эти две таблицы:
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
Я действительно хочу узнать, есть ли в официальной документации Oracle об этом
Не забывайте, что в Oracle, если атрибуты ключа объединения названы одинаково в обеих таблицах, вы также можете записать это как:
select *
from Table1 inner join Table2 using (ID);
Конечно, и у него такой же план запроса.
Я откатил редакцию, потому что предыдущая редакция изменила смысл ответа
[За бонусный балл ...]
Использование синтаксиса JOIN позволяет вам более легко закомментировать соединение, так как все оно находится в одной строке. Этот может будет полезен, если вы отлаживаете сложный запрос.
Как говорят все остальные, функционально они одинаковы, однако JOIN более четкое изложение намерений. Следовательно, май помогает оптимизатору запросов в некоторых случаях в текущих версиях Oracle (я не знаю, помогает ли это), май помогает оптимизатору запросов в будущих версиях Oracle (никто не знает), или май помогает, если вы меняете поставщика базы данных.
Или ... легко измените INNER JOINS на LEFT JOINS, чтобы вы могли видеть, какое соединение заставляет вас пропускать ожидаемые строки. Я делаю это потому, что делаю весь запрос сразу. Если вы закомментируете INNER JOINS, вам придется выполнить процесс исключения. Это займет больше времени. Но +1 для вас, потому что это одна из моих любимых причин для INNER JOINS, помимо удобочитаемости!
Хотя идентичность двух запросов кажется очевидной, иногда случаются странные вещи. Я пришел к запросу, который имеет разные планы выполнения при перемещении предиката соединения из JOIN в WHERE в Oracle 10g (для плана WHERE лучше), но я не могу воспроизвести эту проблему в упрощенных таблицах и данных. Думаю, это зависит от моих данных и статистики. Оптимизатор - довольно сложный модуль и иногда ведет себя волшебно.
Вот почему мы не можем ответить на этот вопрос в целом, потому что это зависит от внутреннего устройства БД. Но мы должны знать, что ответ должен быть «без отличий».
Сегодня у меня возникла эта загадка, когда я проверял тайм-аут одного из наших sp в продакшене, вместо этого заменил внутреннее соединение таблицы, построенной из xml-канала, на предложение 'where' .... среднее время выполнения теперь составляет 80 мс на 1000 выполнений, тогда как до того, как среднее время выполнения было 2,2 секунды ... основное отличие в плане выполнения - исчезновение ключевого поиска ... Сообщение о том, что вы не узнаете, пока не протестируете оба метода.
ваше здоровье.
Просто примечание, много лет спустя - то, что вы наблюдали, скорее всего, было результатом перестроения хранимой процедуры, чем изменения синтаксиса.
В сценарии, где таблицы находятся в 3-й нормальной форме, соединения между таблицами не должны изменяться. Т.е. присоединиться к КЛИЕНТАМ и ПЛАТЕЖИ всегда должны оставаться неизменными.
Однако следует отличать присоединяется от фильтры. Объединения связаны с отношениями, а фильтры - с разделением целого.
Некоторые авторы ссылаются на стандарт (например, Джим Мелтон; Алан Р. Саймон (1993). Понимание нового SQL: полное руководство. Морган Кауфманн. Стр. 11–12. ISBN 978-1-55860-245-8.) , писал о преимуществах использования синтаксиса JOIN для таблиц, разделенных запятыми, в предложении FROM.
Я полностью согласен с этой точкой зрения.
Есть несколько способов написать SQL и добиться тех же результатов, но для многих из тех, кто работает в команде, четкость исходного кода является важным аспектом, и, безусловно, разделение того, как таблицы связаны друг с другом от конкретных фильтров, было большим скачком в смысле прояснения источника код.
Внутреннее соединение включено означает перекрестное соединение где. Запятая - это перекрестное соединение с более низким приоритетом, чем объединение ключевых слов. На vs "фильтр" не имеет отношения к внутреннему соединению. NF не имеют отношения к запросам. Ничто в стандарте не способствует объединению ключевых слов через запятую. Тривиальная оптимизация работает одинаково и везде. Этот ответ - куча заблуждений.
1) Думаю, @philipxy пытается сказать: «В предложении FROM таблицы, разделенные запятой, имеют то же значение, что и таблицы, соединенные CROSS JOINed». Я согласен с этим. Конечно, вы можете придерживаться старого синтаксиса, который может сосуществовать с предложениями JOIN. Оптимизаторы РСУБД прекрасно поймут оба случая как одно и то же (если, конечно, они эквивалентны) и разработают один и тот же план.
Они оба присоединяются и делают то же самое.
Взгляните на Зачем в запросах MySQL использовать join вместо where?
Как сказал Кевик, план выполнения такой же.
Оператор JOIN только легче читается, что позволяет не забыть условие ON и получить декартово произведение. Эти ошибки довольно сложно обнаружить в длинных запросах с использованием нескольких соединений типа: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.
Если вы забудете только одно условие соединения, у вас будет очень много времени на выполнение запроса, возвращающего слишком много записей ... действительно слишком много. Некоторые пользователи используют DISTINCT для исправления запроса, но его выполнение по-прежнему очень долгое.
Именно поэтому использование оператора JOIN, безусловно, является лучшей практикой: лучшая ремонтопригодность и лучшая читаемость.
Более того, если я хорошо помню, JOIN оптимизирован в отношении использования памяти.
У меня есть дополнение к этому хороший ответ:
Это то, что определяется как SQL92 и SQL89 соответственно, между ними нет разницы в производительности, хотя вы можете опустить слово INNER (использование просто JOIN достаточно ясно, и в простейшем запросе вы сохраняете 5 нажатий клавиатуры, теперь представьте, сколько штрихов есть в большом единицы).
просто для записи, я видел, что запросы возвращают разные результаты только при переходе от соединения к предложению where