使用参数化查询时,TVF要慢得多

时间:2015-06-11 22:11:07

标签: sql-server sql-server-2008 user-defined-functions sqlperformance sql-optimization

我正在尝试将内联TVF作为原始参数化SQL查询运行。

当我在SSMS中运行以下查询时,需要 2-3秒

select * from dbo.history('2/1/15','1/1/15','1/31/15',2,2021,default)

我能够通过SQL profiler捕获以下查询(参数化,由Entity框架生成)并在SSMS中运行它。

exec sp_executesql N'select * from dbo.history(@First,@DatedStart,@DatedEnd,@Number,@Year,default)',N'@First date,@DatedStart date,@DatedEnd date,@Maturity int,@Number decimal(10,5)',@First='2015-02-01',@DatedStart='2015-01-01',@DatedEnd='2015-01-31',@Year=2021,@Number=2

在SSMS中运行上述查询需要 1:08 ,这比非参数化版本长约30倍。

我尝试在参数化查询的末尾添加option(recompile),但就性能而言,它绝对没有做任何事情。这对我来说显然是一个索引问题,但我不知道如何解决它。

在查看执行计划时,似乎参数化版本大部分主要挂在 Eager Spool(46%)上,然后是 Clustered Index扫描(30%)< / em>在没有参数的执行计划中不存在。

也许有一些我缺少的东西,有人可以指出我正确的方向,以便我如何让这个参数化的查询正常工作?

编辑:Parameterized query execution plannon-parameterized plan

1 个答案:

答案 0 :(得分:2)

可能它是一个参数嗅探问题。

尝试修改函数,以便将参数设置为局部变量,并使用SQL中的本地变量而不是参数。

所以你的函数会有这个结构

CREATE FUNCTION history(
       @First Date, 
       @DatedStart Date, 
       @DatedEnd Date, 
       @Maturity int, 
       @Number decimal(10,5))
RETURNS @table TABLE (
   --tabledef
) 
AS
BEGIN

   Declare @FirstVar Date = @First
   Declare @DatedStartVar Date = @DatedStart
   Declare @DatedEndVar Date = @DatedEnd
   Declare @MaturityVar int = @Maturity
   Declare @NumberVar decimal(10,5) = @Number

   --SQL Statement which uses the local 'Var' variables and not the parameters 

   RETURN;
END

我过去曾有类似的问题,这是罪魁祸首,映射到局部变量会阻止SQL Server提出dud执行计划。