We have a stored procedure that allows us to create some dynamic SQL and execute using a parameterized call to sp_executesql .
Under normal conditions, this works wonderfully and has been very useful at run time for the procedure (from ~ 8 seconds to ~ 1 second), however, under some unknown conditions, something strange happens and the performance goes completely (~ 31 seconds), but only at execution through RPC (i.e., calling from a .Net application with SqlCommand.CommandType of CommandType.StoredProcedure or as a remote request from a linked server) - if executed as an SQL package using SQL Server Management Studio, we do not see any performance degradation.
Changing the white space in the generated SQL and recompiling the stored procedure seems to fix the problem, at least in the short term, but we would like to understand the reason or ways to make the execution plans rebuild for the generated SQL; but at the moment I'm not sure how to continue working?
To illustrate, a stored procedure looks something like this:
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
With this approach, the query plan will be cached for NULL / not-NULL permutations, and we get the benefits of cached query plans. I do not understand why he will use a different query plan for remote deletion and local after "something happens"; I also do not understand what is "something"?
I understand that I can move away from parameterization, but then we will lose the advantage of caching, which is usually a good execution plan.