我正在尝试将内联 TVF 作为原始参数化 SQL 查询运行。
当我在 SSMS 中运行以下查询时,需要2-3 秒
select * from dbo.history('2/1/15','1/1/15','1/31/15',2,2021,default)
我能够通过 SQL 探查器(参数化,由 Entity Framework 生成)捕获以下查询并在 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%)上,然后是聚集索引扫描(30%) 不存在于不带参数的执行计划中。
也许我缺少一些东西,有人可以给我指出正确的方向,告诉我如何让这个参数化查询正常工作吗?
编辑:Parameterized query execution plan , non-parameterized plan
最佳答案
可能是参数嗅探问题。
尝试修改您的函数,以便将参数设置为局部变量,并在 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 提出无用的执行计划。
关于sql-server - 使用参数化查询时 TVF 速度要慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30792325/