动态SQL和存储过程优化

时间:2012-11-06 21:38:14

标签: sql-server sql-server-2008 stored-procedures dynamic-sql

我已经读过在存储过程中使用动态SQL会损害存储过程的性能。我想理论是存储过程不会存储通过EXEC或sp_executesql执行的SQL的执行计划。

我想知道这是否属实。如果是这样,我是否会遇到多个嵌套IF块的相同问题,每个块都有一个与我的SQL语句不同的“版本”?

2 个答案:

答案 0 :(得分:6)

如果您有多个嵌套的IF块,那么SQL Server将能够存储执行计划。 我假设IF是直截了当的,例如。 IF @ Parameter1 IS NOT NULL

SchmitzIT的答案是正确的,SQL Server也可以存储动态SQL的执行路径。但是,只有在正确构建和执行sql时才会出现这种情况。

通过正确构建,我的意思是显式声明参数并将它们传递给sp_executesql。例如

declare @Param1 nvarchar(255) = 'foo'
        ,@Param2 nvarchar(255) = 'bar'
        ,@sqlcommand nvarchar(max)
        ,@paramList nvarchar(max)

set @paramList = '@Param1 nvarchar(255), @Param2 nvarchar(255)'
set @sqlcommand = N'Select Something from Table where Field1 = @Param1 AND Field2 = @Param2'

exec sp_executesql @statement = @sqlcommand
                  ,@params = @paramList
                  ,@Param1 = @Param1
                  ,@Param2 = @Param2

正如您所看到的,sqlcommand文本不会对要使用的paramer值进行硬编码。它们在exec sp_executesql

中单独传递

如果你写了旧的动态sqL

set @sqlcommand = N'Select Something from Table where Field1 = ' + @Param1  + ' AND Field2 = ' + @Param2

exec sp_executesql @sqlcommand

然后SQL Server将无法存储执行计划

答案 1 :(得分:3)

这就是MSDN对它的评价。我强调了你问题的相关部分

  

对于批处理,sp_executesql与EXECUTE具有相同的行为,   名称范围和数据库上下文。 Transact-SQL语句   sp_executesql @stmt参数中的批处理或批处理直到编译   执行sp_executesql语句。 @stmt的内容是   然后编译并执行作为独立于的执行计划   调用sp_executesql的批处理的执行计划。该   sp_executesql批处理不能引用批处理中声明的变量   调用sp_executesql。本地游标或变量   sp_executesql批处理对于调用的批处理不可见   sp_executesql的。数据库上下文的更改仅持续到最后   sp_executesql语句。

     

可以使用sp_executesql代替存储过程来执行   当参数值发生变化时,Transact-SQL语句多次   声明是唯一的变化。因为Transact-SQL   语句本身保持不变,只有参数值   更改后,SQL Server查询优化器很可能会重用   它为第一次执行生成的执行计划

http://msdn.microsoft.com/en-us/library/ms188001.aspx