Ответ 1
Если какая-либо из этих таблиц является переменными таблицы, оптимизатор использует плохую оценку 0 строк и обычно выбирает вложенный цикл как метод соединения.
Это происходит из-за отсутствия статистики по участвующим таблицам.
Хорошо, поэтому я понимаю, что это довольно неопределенный вопрос, но несите меня.
Я неоднократно сталкивался с этой проблемой с разными и несвязанными запросами. Следующий запрос занимает много минут:
SELECT <Fields>
FROM <Multiple Tables Joined>
LEFT JOIN (SELECT <Fields> FROM <Multiple Tables Joined> ) ON <Condition>
Однако, просто добавив подсказку соединения, запрос выполняется за несколько секунд:
SELECT <Fields>
FROM <Multiple Tables Joined>
LEFT HASH JOIN (SELECT <Fields> FROM <Multiple Tables Joined> ) ON <Condition>
Странно, что тип JOIN, указанный в подсказке, на самом деле не является тем, что улучшает производительность. По-видимому, это связано с тем, что подсказка заставляет оптимизатор выполнять отдельный запрос в отдельности и затем присоединяться. Я вижу такое же улучшение производительности, если я создаю функцию таблицы (не встроенную) для подзапроса. например.
SELECT <Fields>
FROM <Multiple Tables Joined>
LEFT JOIN dbo.MySubQueryFunction() ON <Condition>
У кого-нибудь есть идеи, почему оптимизатор настолько тупой в этом случае?
Если какая-либо из этих таблиц является переменными таблицы, оптимизатор использует плохую оценку 0 строк и обычно выбирает вложенный цикл как метод соединения.
Это происходит из-за отсутствия статистики по участвующим таблицам.
Оптимизатор - это алгоритм. Он не является немым или умным, он работает так, как он запрограммирован.
Hash join
подразумевает построение хэш-таблицы для меньшего источника строки, поэтому сначала должен выполняться внутренний запрос.
В первом случае оптимизатор мог выбрать nested loop
. Он переместил условие соединения во внутренний запрос и выполнил внутренний запрос на каждой итерации с помощью дополнительного предиката. Он может не найти подходящего индекса для этого предиката, а full table scan
- на каждой итерации.
Трудно сказать, почему это происходит, если вы не отправляете свой точный запрос и сколько строк в ваших таблицах.
С помощью функции таблицы невозможно вставить условие соединения во внутренний запрос, поэтому он выполняется только один раз.
Внутри SQL Server 2005: запрос T-SQL отвечает на эти и многие другие вопросы. Один из лучших взглядов под капотом поиска данных T-SQL и обработки глаголов, которые я когда-либо видел. (Нет, я не являюсь автором книги, и я не связан ни с каким автором или авторами книги, или с Microsoft, или с Microsoft Press. Это просто невероятная работа, и различные администраторы баз данных, которые я включил в прошлое пару лет согласны.)