TSQL - Каков правильный порядок объединения таблиц?

Мой гугл-фу и со-фу подводит меня здесь, так что я могу спросить.

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

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

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

Это верно?

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

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

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

2 ответа

Решение

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

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

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 JOINs... попробуйте структурировать ваш запрос, чтобы избежать RIGHT OUTER JOINс, а вместо этого использовать LEFT OUTER JOIN"S.

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

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

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

[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;

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

Другие вопросы по тегам