这是我一段时间以来一直在努力的事情,但总是找到解决方法。
我在SQL Server DW中有一个事实表,它有大约30M条记录,还有一个名为DateCreatedKey的整数字段,该字段在字段上有非聚集索引。
然后我还有一个名为dbo.fn_DateKeyFromDate
的函数,它非常简单
declare @ret int = Year(@date) * 10000 + Month(@date) * 100 + Day(@date)
return @ret
正如您将从下面的执行时间中看到的那样,在使用函数或使用变量时,索引似乎无法正常工作。 不确定我是否遗漏了一些明显的东西?
现在这些是这5个代码块中每个代码的执行时间:
A:0.034s:
SELECT *
INTO #subs2
FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK)
where DateCreatedKey >= 20170814
B:15.4s:
declare @fromdate int
select @fromdate = 20170814
SELECT *
INTO #subs3
FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK)
where DateCreatedKey >= @fromdate
C:134s:
SELECT *
INTO #subs4
FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK)
where DateCreatedKey >= dbo.fn_DateKeyFromDate(GETDATE()-1)
D:20s:
declare @fromdate int
select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1)
SELECT *
INTO #subs
FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK)
where DateCreatedKey >= @fromdate
答案 0 :(得分:1)
我会说在调用函数时不会使用索引,但它应该与变量一起使用。我会比较执行计划以确定。
如果你想使用这个功能试试这个(也许你的想法是130s的例子?):
declare @fromdate int
select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1)
SELECT *
INTO #subs
FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK)
where DateCreatedKey >= @fromdate
答案 1 :(得分:1)
我必须看到C的查询计划,但我认为它会指向我的功能。但是A很快,因为你使用的是文字而SQL知道如何处理这个值。
由于使用局部变量,B和D较慢。请在此处阅读:https://www.brentozar.com/archive/2014/06/tuning-stored-procedures-local-variables-problems/
我想如果你创建了一个存储过程并传入了值,你的执行时间就会大大减少。
或者您可以通过添加RECOMPILE查询提示来测试它,这将允许优化器使用正确的统计信息。