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 JOIN
s... попробуйте структурировать ваш запрос, чтобы избежать 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;
Первый выбор выполняет два сканирования индекса, второй выполняет сканирование и поиск. Это еще одна веская причина избегать намеков.