Почему при объединении SQL выбирается неоптимальный план запроса? - PullRequest
15 голосов
/ 07 февраля 2009

Хорошо, я понимаю, что это довольно расплывчатый вопрос, но потерпите меня.

Я неоднократно сталкивался с этой проблемой при разных и не связанных запросах. Выполнение запроса ниже занимает много минут:

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>

У кого-нибудь есть идеи, почему оптимизатор такой тупой в этом случае?

Ответы [ 3 ]

14 голосов
/ 07 февраля 2009

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

Это происходит из-за отсутствия статистики по используемым таблицам.

7 голосов
/ 07 февраля 2009

Оптимизатор - это алгоритм. Он не тупой или умный, он работает так, как запрограммирован.

Hash join подразумевает построение хэш-таблицы на меньшем источнике строк, поэтому внутренний запрос должен выполняться первым.

В первом случае оптимизатор мог выбрать nested loop. Он вставил условие соединения во внутренний запрос и выполнял внутренний запрос на каждой итерации с дополнительным предикатом. Возможно, не найден подходящий индекс для этого предиката, и full table scan имел место на каждой итерации.

Трудно сказать, почему это происходит, если вы не отправили точный запрос и сколько строк в ваших таблицах.

С табличной функцией невозможно вставить условие соединения во внутренний запрос, поэтому оно выполняется только один раз.

0 голосов
/ 05 декабря 2009

Внутри SQL Server 2005: T-SQL Querying отвечает на эти и многие другие вопросы. Один из лучших вариантов поиска данных и обработки глаголов в T-SQL, который я когда-либо видел. (Нет, я не являюсь автором книги, я не связан ни с одним автором или авторами книги, ни с Microsoft, ни с Microsoft Press. Это просто невероятная работа, и различные администраторы баз данных, к которым я обращался в прошлом пару лет согласен.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...