2011-03-29 81 views
2

我从.net调用一些参数化的sql。我不知道为什么,但在SQL如果参数为空时相比,其不包括对检查时运行非常缓慢:参数化SQL和NULL运行缓慢

所以这个:

exec sp_executesql N' 
SELECT [id] 
FROM [tblAddress] (nolock) 
WHERE 1 = 1 
AND ([id] = @id OR @id IS NULL) 

',N'@id int', 
@id=4395 

奔跑越快,这一点:

exec sp_executesql N' 
SELECT [id] 
FROM [tblAddress] (nolock) 
WHERE 1 = 1 
AND ([id] = @id) 

',N'@id int', 
@id=4395 

运行SQL事件探查器超过100万行的顶部查询的持续时间为175,其读取为3720,但第二个查询的持续时间为1且只有3个读取。

为什么会有这样的差异,怎么能改进?

回答

5

or子句是不是可优化搜索,这样使用的计划有一个扫描,而不是寻求像:第二个

试试这个:2寻求

SELECT [id] 
FROM [tblAddress] 
WHERE [id] = @id 
UNION ALL 
SELECT [id] 
FROM [tblAddress] 
WHERE @id IS NULL) 

注意:您不需要NOLOCK提示。或者1=1

+0

这样更快,谢谢。我不明白为什么它会扫描给定'@id IS NULL'语句不需要表? – 2011-03-29 05:07:59

+0

'1 = 1'又如何加快速度?它是否总是在使用OR语句时进行扫描,而不管正在评估什么? – 2011-03-29 05:11:07

+0

1 = 1仅适用于dnycmic SQL,因此我认为您需要它。这不是必需的。 @ID仍然是一个参数,所以需要包含在计划中,当它不是NULL时。但是,为什么你仍然在使用sp_executesql ...? – gbn 2011-03-29 05:12:56

1

如果@id为NULL,那么你无法做到SEEK,所以它总是会扫描,并且总是很慢(取决于[tblAddress]中的行数)。 。可能希望通过指定TOP(N)子句来限制结果的数量,您的查询返回

所以我会做的是:

IF @id IS NOT NULL 
BEGIN 
    SELECT [id] 
     FROM [tblAddress] 
    WHERE [id] = @id 
END 
ELSE 
BEGIN 
    SELECT TOP(20) [id] FROM [tblAddress] 
END 

而且,我不会使用NOLOCK提示如果它不是严格要求。