2017-01-25 3 views
3

У меня есть таблица, таблица, с двумя столбцами, PKColumn1 и Column2 в базе данных SQL Server. Таблица имеет кластеризованный индекс, сгруппированный по PKColumn1.Сканирование, где я ожидаю увидеть поиск

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

SELECT PKColumn1 
FROM Table 
WHERE PKColumn1 = 1 

который он должным образом делает.

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

DECLARE @PKColumn1 INT = 1; 
SELECT PKColumn1 
FROM Table 
WHERE (PKColumn1 = @PKColumn1 OR @PKColumn1 IS NULL) 

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

Почему это?

+0

какая версия sql, которую вы используете – TheGameiswar

ответ

3

В вашем втором запросе проблема заключается в вашем где п:

WHERE (PKColumn1 = @PKColumn1 OR @PKColumn1 IS NULL).

SQL Server не делает каких-либо короткого замыкания (например, в C# ||), что означает, что даже если выражение @PKColumn1 IS NULL истинно, нет никакой гарантии, что SQL сервер не будет оценивать второе выражение PKColumn1 = @PKColumn1.

Решение:

Лучший способ справиться с такими необязательные параметры, чтобы использовать динамический SQL и встроенный запрос на лету. Что-то вроде ....

DECLARE @PKColumn1 INT = 1 
     ,@Sql NVARCHAR(MAX); 

SET @Sql = N' SELECT PKColumn1 
       FROM Table 
       WHERE 1 = 1 ' 
     + CASE WHEN @PKColumn1 IS NOT NULL THEN 
      N' AND PKColumn1 = @PKColumn1 ' ELSE N'' END 

Exec sp_executesql @Sql 
        ,N'@PKColumn1 INT' 
        ,@PKColumn1 

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