Использование переменных в запросе генерирует другой запрос - PullRequest
0 голосов
/ 25 февраля 2011

Почему один и тот же запрос с переменными и без них генерирует разные планы запросов?Например, следующий запрос:

DECLARE @p0 Int = 103
DECLARE @p1 Int = 1
DECLARE @p2 Int = 38
DECLARE @p3 Int = 103
DECLARE @p4 Int = 1

SELECT [t5].[pkCompanyID] AS [CompanyID], [t5].[name] AS [Name], [t5].[imageurl] AS [ImageURL]
FROM (
    SELECT [t0].[pkCompanyID], [t0].[name], [t1].[imageurl], 
        (CASE 
            WHEN EXISTS(
                SELECT NULL AS [EMPTY]
                FROM [tblCompany] AS [t2]
                WHERE ([t2].[fkCompToCompID] = ([t0].[pkCompanyID])) AND (EXISTS(
                    SELECT NULL AS [EMPTY]
                    FROM [tblUserToGroupToCompany] AS [t3]
                    INNER JOIN [tblGroupToApplication] AS [t4] ON [t3].[fkGroupID] = [t4].[fkGroupID]
                    WHERE ([t3].[fkCompanyID] = [t2].[pkCompanyID]) AND ([t3].[fkUserID] = @p0) AND ([t4].[fkApplicationID] = @p1)
                    ))
                ) THEN 1
            ELSE 0
         END) AS [value], [t0].[fkCompToCompID]
    FROM [tblCompany] AS [t0]
    LEFT OUTER JOIN [tblNodeTypes] AS [t1] ON [t1].[pkNodeTypeID] = [t0].[fkNodeTypeID]
    ) AS [t5]
WHERE (([t5].[value] = 1) OR (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [tblUserToGroupToCompany] AS [t6]
    WHERE [t6].[fkCompanyID] = [t5].[pkCompanyID]
    ))) AND ([t5].[fkCompToCompID] = @p2) AND (EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [tblUserToGroupToCompany] AS [t7]
    INNER JOIN [tblGroupToApplication] AS [t8] ON [t7].[fkGroupID] = [t8].[fkGroupID]
    WHERE ([t7].[fkCompanyID] = [t5].[pkCompanyID]) AND ([t7].[fkUserID] = @p3) AND ([t8].[fkApplicationID] = @p4)
    ))

Создает этот план (часть плана) enter image description here

Но тот же запрос, если я обмениваю переменные на значения непосредственно в запросе.например,

...WHERE ([t7].[fkCompanyID] = [t5].[pkCompanyID]) AND ([t7].[fkUserID] = 103) AND ([t8].[fkApplicationID] = 1)

создает этот план (та же часть, что и другие) enter image description here

В этом плане также есть другие изменения, но я не могу вписать все изображение здесь.Первый запрос примерно на 50% быстрее второго.

1 Ответ

2 голосов
/ 25 февраля 2011

Поскольку при использовании значений FIXED с отключенной функцией AUTO-PARAMETERIZATION план запроса точно знает, для какого значения ему нужно выполнить запрос.Таким образом, план настраивается ОСОБЕННО на эти значения.

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

В SQL Server 2008 вы можете указать, будут ли автоматически параметрироваться простые параметры, чтобы вы последовательно получали «лучший средний случай»"План - со всеми его хорошими и плохими.

Ссылка:

EDIT - по производительности

Что касается производительности, оптимизатор может ошибиться - в этом случае он посмотрел статистику for the exact values и почувствовал, что индексбесполезен (может быть, это переломный момент), поэтому план предназначен для кластерного сканирования.Это тонкое искусство в отношении того, следует ли форсировать план запроса, но ясно, что использование индекса на 50% быстрее для

  1. конкретного оборудования
  2. определенного момента времени распределения данных
  3. заданные конкретные значения

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

...