2015-08-23 4 views
-2

У меня есть хранимая процедура. Если я использую where (@detailId равно null или SalesOrderDetailID = @detailId), то используется некластеризованный индекс, но если я изменил предложение where на SalesOrderDetailID = @detailId, то будет использоваться индекс с кластером.почему вместо кластеризованного индекса используется некластеризованный индекс

Проверьте приведенную ниже процедуру. Первичный ключ - это комбинация столбцов - (SalesOrderID, SalesOrderDetail).

alter procedure samproc 

@detailId int = null 

with recompile 
as 
begin 

select SalesOrderID 
from sales.SalesOrderDetail 
where (@detailId is null or SalesOrderDetailID = @detailId) 

end 
go 

exec dbo.samproc @detailId = 1 

Вопрос - почему кластеризованный индекс не используется, когда я использую или условие в предложении where. Мне нужно использовать или потому, что хотите пропустить где состояние, если параметр не passed.I также используется

where isnull(@detailId,SalesOrderDetailID) 

но реальный сценарий-х у меня есть 10 параметров, и это может быть дорогостоящим, поскольку индекс столбцов внутри IsNull функции не будет и во-вторых isnull вызывает сканирование таблицы. Именно по этой причине я использовал

where (@detailId is null or SalesOrderDetailID = @detailId) 

Может кто-нибудь сказать мне, как избежать некластеризованного индекса и использовать кластерный индекс.

+0

Если вы чувствуете, что определенный индекс обеспечивает лучшую производительность, чем тот, который выбрал SQL Server, вы можете заставить его использовать этот индекс. –

+1

'SalesOrderDetailID = isnull (@ detailId, SalesOrderDetailID)' IS SARGable "SQL Server не может использовать индексный указатель при применении функции к столбцу« – lad2025

ответ

1

Использование индекса с or является хлопотным. Лучше всего построить динамическую инструкцию SQL и выполнить ее:

declare @sql nvarchar(max) = ' 
select SalesOrderID 
from sales.SalesOrderDetail 
where 1=1 '; 

if (@detailId is not null) 
begin 
    @sql := @sql + 'SalesOrderDetailID = ' + cast(@detailId as varchar(255)); 
end; 

exec sp_execute_sql @sql; 

Примечание: вам следует, вероятно, сделать это с помощью параметров. , ,

declare @sql nvarchar(max) = ' 
select SalesOrderID 
from sales.SalesOrderDetail 
where 1 = 1 '; 

if (@detailId is not null) 
begin 
    @sql := @sql + 'and SalesOrderDetailID = @detailid'; 
end; 

exec sp_execute_sql @sql, '@detailid int', @detailid = @detailid 

Результат будет более простым утверждением, которое может лучше использовать индексы.

+0

Но как вы собираетесь давать, если (@detailId не является нулевым) условием когда есть 10 параметров. Сколько nestede ifs вы возьмете в этом случае. – sam

+0

@sam Вы прочитали ответы на свой [предыдущий вопрос] (http://stackoverflow.com/questions/32153904/how-to-ignore-a-parameter-in- хранимая процедура, если его-значение-это-нуль)? – lad2025

+0

@ lad2025 Да, вы используете условие IF только для одного параметра; Можете ли вы рассказать мне, что произойдет, если var1 не равен null, а var2 - null. В каком из ваших условий будет присутствовать этот случай. Позвольте мне сказать вам, в этом случае ни одно из ваших условий if не будет выполнено. Поскольку вы должны были использовать -IF var1 IS NOT NULL, а var2 - null – sam

Смежные вопросы