Критерии фильтрации SQL в предложении join criteria или where, которое является более эффективным

StackOverflow https://stackoverflow.com/questions/1401889

Вопрос

У меня есть относительно простой запрос, соединяющий две таблицы.Критерии "Where" могут быть выражены либо в критериях объединения, либо в виде предложения where.Мне интересно, что из этого более эффективно.

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

Случай 1

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
                  and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

Случай 2

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

Обратите внимание, что в случае 1 вообще отсутствует предложение where

СУБД - это Sql Server 2005

Редактировать Если второй частью критерия объединения или предложения where были продажи.дата продажи < некоторая фиксированная дата, так что на самом деле никаких критериев объединения двух таблиц нет, это меняет ответ.

Это было полезно?

Решение

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

Я бы всегда использовал вариант № 2 - почему?Потому что, на мой взгляд, вы должны поместить только фактические критерии, которые устанавливают СОЕДИНЕНИЕ между двумя таблицами, в предложение JOIN - все остальное принадлежит предложению WHERE .

Просто вопрос в том, чтобы содержать вещи в чистоте и расставлять их по местам, ИМО.

Очевидно, что есть случаи с ЛЕВЫМИ ВНЕШНИМИ объединениями, где размещение критериев действительно имеет значение с точки зрения того, какие результаты будут возвращены - эти случаи, конечно, были бы исключены из моей рекомендации.

Марк

Другие советы

Вы можете запустить оценщик плана выполнения и профилировщик sql, чтобы посмотреть, как они соотносятся друг с другом.

Тем не менее, они семантически одинаковы под капотом в соответствии с этим SQL Server MVP:

http://www.eggheadcafe.com/conversation.aspx?messageid=29145383&threadid=29145379

Я предпочитаю иметь какие-либо жестко закодированные критерии в join.Это делает SQL намного более читабельным и переносимым.

Удобочитаемость:Вы можете точно видеть, какие данные вы собираетесь получить, потому что все критерии таблицы записаны прямо там, в соединении.В больших выражениях критерии могут быть скрыты в пределах 50 других выражений и их легко пропустить.

Переносимость:Вы можете просто скопировать фрагмент из предложения FROM и вставить его в другое место.Это дает объединения и любые критерии, которые вам нужны для этого.Если вы всегда используете этот критерий при объединении этих двух таблиц, то наиболее логичным будет поместить его в join.

Например:

FROM
table1 t1
JOIN table2 t2_ABC ON
  t1.c1 = t2_ABC.c1 AND
  t2_ABC.c2 = 'ABC'

Если вам нужно получить второй столбец из таблицы 2, вы просто копируете этот блок в Блокнот, выполняете поиск / замену "ABC" и presto, и весь новый блок кода готов для вставки обратно.

Дополнительный:Также проще переключаться между внутренним и внешним соединением, не беспокоясь о каких-либо критериях, которые могут быть плавающими в предложении WHERE.

Я оставляю предложение WHERE строго для критериев времени выполнения, где это возможно.

Что касается эффективности:Если вы имеете в виду скорость выполнения, то, как уже заявляли все остальные, это избыточно.Если вы имеете в виду более простую отладку и повторное использование, то я предпочитаю вариант 1.

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

Но я выделил одно отличие, которое вы можете использовать для своих логических нужд..

  1. Используя критерии в ВКЛ . предложение не будет фильтровать / пропускать строки для выбора, вместо этого столбцы объединения будут иметь значение null в зависимости от условий

  2. Используя критерии в Где предложение может фильтровать / пропускать строки во всех результатах

Я не думаю, что вы найдете окончательный ответ на этот вопрос, который применим ко всем случаям.Эти 2 не всегда взаимозаменяемы - поскольку для некоторых запросов (некоторых левых объединений) вы получите разные результаты, поместив критерии в строку WHERE и FROM.

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

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

Попробуйте это, чтобы увидеть разницу между этими двумя...

SET STATISTICS IO ON
SET STATISTICS TIME ON

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid =sales.salesmanid
       and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where  sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

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

На мой взгляд, они кажутся эквивалентными, поэтому анализатор запросов вполне может выдавать идентичные планы, но вам придется протестировать.

Ни то, ни другое не является более эффективным, поскольку использование метода WHERE считается старым способом сделать это (http://msdn.microsoft.com/en-us/library/ms190014.aspx).Вы можете посмотреть на план выполнения и увидеть, что они делают то же самое.

Ознакомьтесь с Предполагаемым планом выполнения в SQL Management Studio!!Как уже говорили другие, вы находитесь во власти анализатора, что бы вы ни делали, поэтому доверяйте его оценкам.Я бы предположил, что те два, которые вы предоставили, приведут к точно такому же плану.

Если это попытка изменить культуру разработки, выберите ту, которая дает вам лучший план;для тех, которые идентичны, следуйте культуре

Я комментировал это в других постах "эффективности", подобных этому (они одновременно искренни и саркастичны) - если это то, где находятся ваши узкие места, то пять вам и вашей команде.

Случай 1 (критерии в СОЕДИНЕНИИ) лучше подходит для инкапсуляции, и повышенная инкапсуляция обычно является хорошей вещью:уменьшено количество пропусков при копировании / вставке в другой запрос, уменьшено количество ошибок при последующем преобразовании в СОЕДИНЕНИЕ по ЛЕВОМУ краю и повышена удобочитаемость (связанные материалы собраны вместе и меньше "шума" в предложении WHERE).В этом случае предложение WHERE фиксирует только основные критерии таблицы или критерии, охватывающие несколько таблиц.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top