лучше добавить больше логики в ваше предложение ON или он должен иметь только необходимый минимум? - PullRequest
7 голосов
/ 01 мая 2009

Учитывая эти два запроса:

Select t1.id, t2.companyName 
from table1 t1 
  INNER JOIN table2 t2 on t2.id = t1.fkId 
WHERE t2.aField <> 'C' 

ИЛИ:

Select t1.id, t2.companyName 
from table1 t1 
  INNER JOIN table2 t2 on t2.id = t1.fkId  and t2.aField <> 'C'

Есть ли очевидная разница между ними? Сдается мне, что предложение "t2.aField <> 'C'" будет выполняться в каждой строке в t2, которая в любом случае соответствует критериям соединения. Я не прав?

Обновление: Я сделал «Включить фактический план выполнения» в SQL Server. Два запроса были идентичны.

Ответы [ 6 ]

4 голосов
/ 01 мая 2009

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

Я надеюсь (хотя у меня нет статистики), что SQL Server будет достаточно умен, чтобы найти оптимальный план запроса независимо от используемого вами синтаксиса.

ОДНАКО, если у вас есть индексы, в которых также есть id и aField, я бы предложил поместить их вместе в критерии внутреннего соединения.

Было бы интересно увидеть план запроса в этих 2 (или 3) сценариях и посмотреть, что произойдет. Хороший вопрос.

3 голосов
/ 01 мая 2009

Есть разница. Вы должны сделать EXPLAIN PLAN для обоих вариантов выбора и увидеть его подробно.

Что касается более простого объяснения: Предложение WHERE выполняется только после объединения двух таблиц, поэтому оно выполняется для каждой строки, возвращаемой из объединения, а не для каждой из таблицы table2.

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

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

2 голосов
/ 01 мая 2009

Это зависит.

SELECT
  t1.foo,
  t2.bar
FROM
  table1 t1
  LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId
WHERE
  t2.SomeValue IS NULL

отличается от

SELECT
  t1.foo,
  t2.bar
FROM
  table1 t1
  LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId AND t2.SomeValue IS NULL

Отличается тем, что первая вычеркивает все записи из t2, имеющие NULL в t2.SomeValue и те из t1, на которые нет ссылок в t2. Последний вычеркивает только те записи t2, которые имеют значение NULL в t2.SomeValue.

Просто используйте предложение ON для условия соединения и предложение WHERE для фильтра.

1 голос
/ 01 мая 2009

Если перемещение условия соединения к предложению where не изменит значения запроса (как в примере с левым соединением выше), то не имеет значения, куда вы их помещаете. SQL будет переупорядочивать их, и пока они доказуемо эквивалентны, вы получите один и тот же запрос.

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

0 голосов
/ 01 мая 2009

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

Ответы, в которых упоминаются планы запросов, дают хороший совет.

Кроме того, установите статистику io, чтобы получить представление о том, сколько запросов будет генерировать ваш запрос (особенно мне нравится пост Аздера).

Думайте о каждом сервере БД как о прокачке данных с диска на клиент. Этот насос работает быстрее, если он выполняет только ввод-вывод, необходимый для выполнения работы. Если данные находятся в кеше, это будет еще быстрее. Но вы не хотите читать с диска больше, чем нужно - это приведет к вытеснению из вашего кеша полезных данных без веской причины.

0 голосов
/ 01 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...