当涉及变量/函数时,简单的SQL Server查询将永远占用

时间:2017-08-15 08:37:57

标签: sql-server tsql

这是我一段时间以来一直在努力的事情,但总是找到解决方法。 我在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
    

2 个答案:

答案 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查询提示来测试它,这将允许优化器使用正确的统计信息。

相关问题