sp_executesql和选项重新编译之间有什么区别

时间:2015-10-05 10:32:59

标签: sql-server sql-server-2008

有人可以告诉我sp_executesql和选项重新编译之间的区别。 它们都会在每次执行查询时创建新的计划。我可以用两种方式创建下面的存储过程 - 如下所述的存储过程或在存储过程中使用sp_executesql。

----------方法1 -------------

create procedure test
@var1 int,
@start date,
@end date

with recompile
as
begin

declare @v1 date
declare @v2 date

set @v1 = @var1
set @v2 = @var2

if @var1 > 0
begin
select a.name,b.name
from table1 as a
inner join table2 as b
on a.id = b.id
where a.id <= @var1 and a.date between @v1 and @v2
end

else if @var1 < 0

begin
select a.name,b.name
from table1 as a
inner join table2 as b
on a.id = b.id
where a.id >= @var1 and a.date between @v1 and @v2
end
end

----------方法2 -------------

create procedure test
@var1 int,
@start date,
@end date

with recompile
as
begin

declare @v1 date
declare @v2 date
declare @sql nvarchar(100)

set @v1 = @var1
set @v2 = @var2

set @sql = 'if ' + @var1 + ' > 0
begin
select a.name,b.name
from table1 as a
inner join table2 as b
on a.id = b.id
where a.id <= ' + @var1 + ' and a.date between ' + @v1 + ' and ' + @v2 +
' end

else if ' + @var1 + ' < 0

begin
select a.name,b.name
from table1 as a
inner join table2 as b
on a.id = b.id
where a.id >= ' + @var1 + 'and a.date between ' + @v1 + ' and ' +  @v2 + 
' end'

exec sp_executesql @sql
end

我在这里有两个问题 - 第一,参数嗅探,第二,计划被重用。对于参数嗅探,我使用局部变量@ var1和@ var2。如果@ var1&gt;,该计划将因条件而异。 0和@ var 1&lt;所以我强制优化器再次使用Option重新编译来创建执行计划。

现在有人可以告诉我为什么上述两种方法中的执行计划不同。两种方法都负责参数嗅探并重新生成执行计划。

也可以有人告诉我sp_executesql和选项重新编译之间的区别。两者的工作方式与每次执行查询时重新生成执行计划的方式相同。如果记录是1百万,为什么会选择哪一个?

1 个答案:

答案 0 :(得分:2)

  

RECOMPILE表示数据库引擎不缓存查询   计划此过程,强制每次编译   执行。有关强制a的原因的更多信息   重新编译,请参阅重新编译存储过程。这个选项不可以   在指定FOR REPLICATION或CLR过程时使用。   https://msdn.microsoft.com/en-us/library/ms187926.aspx

sp_executesql

  

可以使用sp_executesql代替存储过程来执行   当参数值发生变化时,Transact-SQL语句多次出现   声明是唯一的变化。因为Transact-SQL   语句本身保持不变,只有参数值   更改后,SQL Server查询优化器很可能会重用   它为第一次执行生成的执行计划。   https://msdn.microsoft.com/it-it/library/ms188001%28v=sql.120%29.aspx