У меня две таблицы
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Эти таблицы имеют некластеризованный индекс на (Id, Date)
И я присоединяюсь к этим таблицам
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Это также можно записать как
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
У меня вопрос, какой из этих двух запросов дает лучшую производительность и почему? Или они равны?
Ответы:
Производительность будет такой же. Оптимизатор распознает это и создаст тот же план.
С другой стороны, я бы не сказал, что они равны. Первая форма в вопросе гораздо более читабельна и обычно ожидаема.
Для примера использования некоторых таблиц, которые у меня есть, вы можете увидеть, что план выполнения точно такой же, независимо от того, как я пишу запрос.
Вы должны быть в состоянии определить планы запросов для ваших собственных таблиц и набора данных, чтобы вы могли видеть, что происходит в вашей ситуации.
Дает эти планы выполнения
источник
INNER JOIN
. Если вы добавите,OUTER JOIN
то они, безусловно, не то же самое.Они семантически идентичны, и у оптимизатора не должно быть проблем с распознаванием этого факта и созданием идентичных планов.
Я склонен ставить условия, ссылающиеся на обе таблицы в,
ON
и условия, ссылающиеся только на одну таблицу вWHERE
.Однако на
OUTER JOINS
перемещение условий может повлиять семантика.источник
В простых случаях это будет то же самое. Однако я видел, что очень сложные запросы с несколькими объединениями имеют существенно разные планы. Недавняя работа, над которой я работал, началась с таблицы, в которой около 6 миллионов строк объединены с примерно 20 различными таблицами. Только первое соединение с этой таблицей было внутренним объединением, все остальные были оставлены внешними объединениями. Фильтр в предложении where был параметризован примерно так:
Этот фильтр был использован позже в плане, а не ранее. Когда я переместил эти условия в первое внутреннее объединение, план кардинально изменился, так как фильтр был применен на раннем этапе в плане, чтобы ограничить набор результатов, а мой ЦП и истекшее время сократились примерно на 310%. Так что, как и во многих вопросах SQL Server, это зависит.
источник
В общем, то, куда вы помещаете фильтры, имеет значение.
В то время как Том V говорит, что Оптимизатор распознает, что запросы одинаковы, и предлагает один и тот же план, это не всегда так. Это зависит от того, какая у вас версия SQL, насколько сложен ваш запрос и насколько важен для всего пакета Оптимизатор определяет запрос.
Оптимизатор может решить, что эта часть пакета не стоит тратить достаточно времени на то, чтобы дать ему наилучший план. В целом вы получите более высокую производительность, если вы поставите условия, которые уменьшают объем данных, над которыми запрос должен будет работать, в предложении ON вместо предложения WHERE (если это возможно, поскольку выполнение этого с внешним объединением приведет к декартовому продукту .)
Временами разработчику SQL немного проще находить фильтры в предложении WHERE, но я работал над некоторыми большими таблицами, где наличие фильтров в предложении ON обрезает часы без времени выполнения.
Поэтому, если предложение может значительно сократить число строк, которые будет считывать запрос, я всегда буду помещать его в предложение ON, чтобы оптимизатор мог выбрать лучший план.
источник
В обычных условиях условия фильтрации могут быть указаны либо в предложениях WHERE, либо в JOIN. Я склонен помещать фильтры в поле WHERE, если только не может быть затронут приоритет OUTER JOIN (см. Ниже) или если фильтр очень специфичен для этой таблицы (например, TYPE = 12 для указания определенного подмножества строк в таблице).
С другой стороны, предложения ON и WHERE могут использоваться для указания условий соединения (в отличие от условий фильтрации). Пока вы используете только ВНУТРЕННИЕ объединения, все равно не будет иметь значения, что вы используете при обычных обстоятельствах.
Однако, если вы используете соединения OUTER, это может иметь большое значение. Если, например, вы указываете OUTER JOIN между двумя таблицами (t1 и t2), но затем в предложении WHERE продолжаете указывать отношение eqijoin между таблицами (например, t1.col = t2.col), вы просто преобразовал НАРУЖНОЕ объединение в ВНУТРЕННЕЕ объединение! Это связано с тем, что WHERE может использоваться для указания эквиджоин (или, может быть, даже OUTER join, в зависимости от версии, с использованием устаревшего синтаксиса * =) без использования предложения ON, и когда WHERE указывает внутреннее эквайоин между таблицами, он переопределяет OUTER ПРИСОЕДИНЯЙТЕСЬ (если есть).
Первоначальный вопрос был о фильтрах, где тип объединения часто не должен быть проблемой, но объединение также может выступать в качестве фильтра, и в таких ситуациях размещение условия объединения, безусловно, может иметь значение.
источник
С INNER JOINs это проблема стиля.
Тем не менее, это становится намного интереснее с OUTER JOIN. Вы должны изучить различия между запросами с OUTER JOIN и условиями как в предложении ON, так и в предложении WHERE. Набор результатов не всегда одинаков. Есть, например,
такой же как
источник