Я слышал смешанную информацию по этому поводу и надеюсь на каноническое или экспертное мнение.
Если у меня есть несколько LEFT OUTER JOIN
s, каждый из которых зависит от последнего, лучше ли их вкладывать?
Для надуманного примера, JOIN
to MyParent
зависит от JOIN
to MyChild
:
http://sqlfiddle.com/#!3/31022/5
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
По сравнению с http://sqlfiddle.com/#!3/31022/7
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
(
MyChild AS c
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
)
ON c.[Id] = gc.[ParentId]
Как показано выше, они производят разные планы запросов в SS2k8
JOIN
этоINNER JOIN
ON ... ON
двух подряд (в скобках или нет) очень сбивает с толку.use plan
Намек работает при пересадке второго плана запроса на первый , но не наоборот.Ответы:
Это абсолютно не канонический ответ, но я заметил, что для планов запросов с вложенными циклами, показанных в скрипте SQL, можно было применить план из Query 2 к Query 1 с использованием
USE PLAN
подсказки, но попытка выполнить обратную операцию не удалась с помощьюОтключение правила преобразования оптимизатора также
ReorderLOJN
предотвращает успешное выполнение ранее выполненной подсказки плана.Эксперименты с большим количеством данных показывают, что SQL Server, безусловно, способен преобразовываться
(A LOJ B) LOJ C
вA LOJ (B LOJ C)
естественные условия, но я не видел никаких доказательств того, что обратное верно.Очень надуманный случай, когда первый запрос работает лучше, чем второй
Который дает планы
Для меня Query 1 имел истекшее время 108 мс против 1163 мс для Query 2.
Запрос 1
Запрос 2
Таким образом, можно условно предположить, что первый («неопубликованный») синтаксис потенциально полезен, поскольку позволяет учитывать больше потенциальных порядков соединения, но я не провел достаточно исчерпывающего тестирования, чтобы иметь большую уверенность в этом как общем правиле.
Вполне возможно, можно придумать встречные примеры, где Query 2 работает лучше. Попробуйте оба и посмотрите на планы выполнения.
источник
нет такого типа JOIN, который называется «Nested Join». это еще один вариант написания JOIN, предназначенный для удобства чтения. Вы можете видеть их как «Подзапросы» только для понимания цели.
если вы больше беспокоитесь о читаемости кода, то я считаю, что они могут выбирать сами.
И если вас беспокоит производительность запроса, а подсказка «Force JOIN ORDER» не используется в запросе, то не имеет значения, написан ли запрос с помощью «Nested Join» или All «Outer Join». SQL-сервер предлагает порядок, основанный на стоимости соединения двух таблиц и / или результате. SQL Server выполняет СОЕДИНЕНИЕ только между двумя наборами данных.
на самом деле, представьте себе, что во втором случае «вложенное соединение», если SQL-сервер решает выполнить вторую часть, «MyChild AS c LEFT OUTER JOIN MyParent AS p ON p. [id] = c. [ParentId]» и эти таблицы происходят иметь строки, которые собираются отбросить в СЛЕДУЮЩЕМ ЛЕВОМ СОЕДИНЕНИИ. в этом случае сервер SQL потратил ненужные ресурсы на выполнение этих двух операций OUTER JOIN и передачу этого результата следующему JOIN.
Вы также можете посмотреть аналогичный вопрос, заданный и соответствующий ответ здесь. Понимание синтаксиса «вложенного соединения»
источник
FORCE JOIN ORDER
подсказки?