我們有一個存儲過程,它構建一些動態SQL並通過參數化調用sp_executesql
執行。爲什麼存儲過程在遠程執行到本地時會執行不同的操作?
在正常情況下,這個功能非常出色,並且在程序的執行時間(~8秒〜1秒)中獲得了很大的好處,但是在某些未知的情況下,出現了一些奇怪的事情,其他方式(〜31秒),但只有在通過RPC執行時(即從.Net應用程序調用SqlCommand.CommandType
的CommandType.StoredProcedure
;或作爲來自鏈接服務器的遠程查詢) - 如果使用SQL Server Management作爲SQL批處理執行工作室,我們看不到性能下降。
改變生成的SQL中的空白並重新編譯存儲過程似乎至少在短期內解決了這個問題,但我們想要了解原因或強制執行計劃的方法爲生成的SQL重新生成;但目前,我不知道如何繼續進行?
爲了說明,存儲過程,看起來有點像:
CREATE PROCEDURE [dbo].[usp_MyObject_Search]
@IsActive AS BIT = NULL,
@IsTemplate AS BIT = NULL
AS
DECLARE @WhereClause NVARCHAR(MAX) = ''
IF @IsActive IS NOT NULL
BEGIN
SET @WhereClause += ' AND (svc.IsActive = @xIsActive) '
END
IF @IsTemplate IS NOT NULL
BEGIN
SET @WhereClause += ' AND (svc.IsTemplate = @xIsTemplate) '
END
DECLARE @Sql NVARCHAR(MAX) = '
SELECT svc.[MyObjectId],
svc.[Name],
svc.[IsActive],
svc.[IsTemplate]
FROM dbo.MyObject svc WITH (NOLOCK)
WHERE 1=1 ' + @WhereClause + '
ORDER BY svc.[Name] Asc'
EXEC sp_executesql @Sql, N'@xIsActive BIT, @xIsTemplate BIT',
@xIsActive = @IsActive, @xIsTemplate = @IsTemplate
通過這種方法,查詢計劃將被緩存爲NULL /不爲NULL的排列,和我們獲得緩存查詢計劃的好處。我不明白的是,爲什麼在「發生某些事情」之後,在遠程執行與本地執行時使用不同的查詢計劃;我也不明白「什麼」可能是什麼?
我意識到我可以移動從參數化了,但那麼我們就會失去緩存是什麼通常良好的執行計劃的好處。
您是否顯示2個計劃已準備好?或者它使用相同的計劃? – badbod99 2010-09-09 11:41:49
@ badbod99它將爲傳遞給'EXEC sp_executesql'的不同字符串創建一個不同的Prepared Compiled Plan,並且這與父存儲過程的編譯無關。無論如何,這必須是這種情況,因爲這些字符串可能涉及完全不同的對象。 – 2010-09-09 12:07:30
好點,execute_sql本身就是一個SP(它看起來像是帶有RECOMPILE查詢提示集),因此根據傳入的數據編譯它自己的執行計劃。所以理論上,使用這個問題不應該發生。仍值得重新編譯。 – badbod99 2010-09-09 12:48:57