Условие внутри соединения или где
есть ли разница (производительность, передовой практики и т. д...) между помещением условия в предложение JOIN и предложением WHERE?
например...
-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'
-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'
что вы предпочитаете (и, возможно, почему)?
9 ответов:
реляционная алгебра допускает взаимозаменяемость предикатов в
WHEREп. иINNER JOIN, да ещеINNER JOINзапросWHEREпредложения могут иметь предикаты, переупорядоченные оптимизатором так, что они может быть уже исключен во время
для внутренних соединений я действительно не заметил разницы (но, как и во всех настройках производительности, вам нужно проверить свою базу данных в ваших условиях).
однако, где вы ставите условие имеет огромное значение, если вы используете левые или правые соединения. Например, рассмотрим эти два запроса:
SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderDate >'20090515' SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID AND ORD.OrderDate >'20090515'первый даст вам только те записи, которые имеют заказ, датированный позже 15 мая 2009 года, таким образом, Преобразуя левое соединение во внутреннее соединение. Этот во-вторых, даст эти записи плюс любые клиенты без заказов. Набор результатов очень отличается в зависимости от того, где вы ставите условие. (Выберите * если, например, только для целей, вы не должны использовать, конечно, в производственном коде.) Исключение - это когда вы хотите видеть только записи в одной таблице, но не в другой. Затем вы используете предложение where для условия, а не для соединения.
SELECT * FROM dbo.Customers AS CUS LEFT JOIN dbo.Orders AS ORD ON CUS.CustomerID = ORD.CustomerID WHERE ORD.OrderID is null
большинство продуктов РСУБД оптимизируют оба запроса одинаково. В "настройке производительности SQL" Питера Гулуцана и Труди Пельцер они протестировали несколько марок СУБД и не обнаружили разницы в производительности.
Я предпочитаю держать условия соединения отдельно от условий ограничения запроса.
Если вы используете
OUTER JOINиногда необходимо поставить условия в предложение join.
где будет фильтр после соединения произошло.
фильтр на соединении, чтобы предотвратить добавление строк во время процесса соединения.
Я предпочитаю JOIN для объединения полных таблиц / представлений, а затем использовать WHERE для введения предиката результирующего набора.
Он чувствует себя синтаксически чище.
Я обычно вижу увеличение производительности при фильтрации на соединении. Особенно если вы можете объединить индексированные столбцы для обеих таблиц. Вы должны быть в состоянии сократить логические чтения с большинством запросов, которые делают это тоже, что в среде с большим объемом является гораздо лучшим показателем производительности, чем время выполнения.
Я всегда слегка удивляюсь, когда кто-то показывает их бенчмаркинг SQL, и они выполнили обе версии sproc 50 000 раз в полночь на сервере dev и сравните среднее время.
помещение условия в соединение кажется мне "семантически неправильным", так как это не то, что объединяет"для". Но это очень качественно.
дополнительная проблема: если вы решите переключиться с внутреннего соединения, скажем, на правое соединение, наличие условия внутри соединения может привести к неожиданным результатам.
соединения быстрее, на мой взгляд, когда у вас есть большая таблица. Это действительно не так много разницы, хотя, особенно если вы имеете дело с довольно небольшим столом. Когда я впервые узнал о соединениях, мне сказали, что условия в соединениях точно такие же, как условия предложения where, и что я мог бы использовать их взаимозаменяемо, если предложение where было конкретным о том, в какой таблице выполнять условие.
лучше добавить условие в соединении. Производительность важнее, чем читаемость. Для больших наборов данных это имеет значение.
Comments