2011-03-29 80 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提示如果它不是嚴格要求。