Подтвердить что ты не робот

TSQL - Каков надлежащий порядок подключения таблиц?

Мой google-fu и so-fu не могут меня здесь, поэтому я мог бы также спросить.

У меня много запросов с несколькими объединениями в них.

В одном запросе я соединяю заголовок/элемент/детали вместе, а также просматриваю различные биты информации для этих записей.

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

Это правильно?

Лучше ли присоединиться к более крупным таблицам перед поисковыми таблицами? Или наоборот?

Должен ли я использовать подсказку loop при соединении с маленькими таблицами и подсказку merge при присоединении к openrowsets?

Я уверен, что ответ "это зависит", но некоторые общие рекомендации по эффективному и эффективному подключению были бы очень полезными. Спасибо!

4b9b3361

Ответ 1

ИЗМЕНИТЬ: В соответствии с вашими комментариями (и Kirk Woll's) вы должны понимать, что порядок ваших объединений является эстетическим и не оказывает прямого воздействия на результат план выполнения. Оптимизатор запросов будет выполнять соединения в наиболее эффективном порядке и использовать соответствующую операцию соединения большую часть времени без каких-либо намеков.

Когда речь заходит об эстетике вашего заказа на объединение, это немного субъективно, но я бы сказал, что объединить ваши таблицы в любом порядке, делая логический смысл при чтении запроса... если вы начнете с @HeaderId, начните с этой таблицей, а затем JOIN в таблицы children:

FROM
    Header h
    JOIN Items i ON h.HeaderId = i.HeaderId
    JOIN Details d ON i.ItemId = d.ItemId
WHERE
    h.HeaderId = @HeaderId

Но если вы запустили свой запрос с помощью @DetailId, я бы присоединился в обратном порядке.

FROM
    Details d
    JOIN Items i ON d.ItemId = i.ItemId
    JOIN Header h ON i.HeaderId = h.HeaderId
WHERE
    d.DetailId = @DetailId

Однако, это субъективное и просто мое личное предпочтение.

Это становится менее субъективным, когда вы начинаете включать OUTER JOIN s... пытайтесь структурировать свой запрос, чтобы избежать каких-либо RIGHT OUTER JOIN s, а вместо этого используйте LEFT OUTER JOIN.

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

Ответ 2

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

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

[1] Я знаю один случай, когда порядок имеет значение:

CREATE TABLE A (
  id int IDENTITY PRIMARY KEY,
  name varchar
);

CREATE TABLE B (
  id int IDENTITY PRIMARY KEY,
  a_id int FOREIGN KEY REFERENCES A (id),
  name varchar
);

SELECT *
FROM A
INNER LOOP JOIN B on A.id = B.a_id;

SELECT *
FROM B
INNER LOOP JOIN A on A.id = B.a_id;

Первый выбор выполняет два сканирования индекса, второй - сканирование и поиск. Это еще одна веская причина избежать подсказок.