【问题标题】:Passing a date parameter to an in-line Table-Valued-Function is sloooww将日期参数传递给内联表值函数很慢
【发布时间】:2012-11-12 15:55:43
【问题描述】:

我在执行表值函数时遇到了一个奇怪的情况。基本上,我有一个以 DATETIME 作为参数的内联表值函数。

看起来像这样(不完全是这样):

  CREATE FUNCTION fn_MyFunction(@StartDate DATETIME)
  RETURNS TABLE
  AS
  RETURN (
    SELECT COUNT(*), CustomerID, SUM(PAID)
    FROM Orders   
    WHERE OrderDate > @StartDate
    GROUP BY CustomerID
  )

现在,我正在尝试调查此查询运行超过 1 分钟的问题。事实证明,如果我这样调用查询:

SELECT * FROM fn_MyFunction('7/1/2011')

运行时间 > 1 分钟。

但是,如果我这样调用查询:

DECLARE @startDate DATETIME = '7/1/2011'
SELECT * FROM fn_MyFunction(@startDate)

它在一秒钟内运行。 SQL Server 对这两个调用使用完全不同的解释计划。

显然,我希望它一直执行第二种方法,不幸的是,我通过 LINQ 2 SQL 调用此表值函数,它不会声明临时变量。

有没有办法可以在内联表值函数中使用临时变量?我真的不想将其转换为多行表值函数。其他想法也将受到欢迎。我有点难过。

【问题讨论】:

  • 在您的测试中,您是否尝试多次运行SELECT * FROM fn_MyFunction('7/1/2011')
  • @约翰。是的。几次。不是缓存问题。
  • 如果您尝试SELECT * FROM fn_MyFunction('7/1/2011') OPTION (RECOMPILE) 以防它被自动参数化怎么办?如果这不起作用,Orders 上的统计信息可能需要更新。
  • 你能把这两个调用的执行计划发一份吗?

标签: sql sql-server-2008 sql-server-2005 tsql


【解决方案1】:

我用大量记录尝试了这个,两种方式都在 9 秒内返回了值,没有 区别……

这是一个很长的镜头,但可以测试一下隐式转换是否为函数提供了与显式转换相同的日期值?尝试使用像“2011/1/30”这样的日期,这样您就会遇到月/日转换问题

【讨论】:

    【解决方案2】:

    添加 OPTION (RECOMPILE) 将解决您的问题。我对内联 TVF 有完全相同的问题,如下所示:

    这条语句在不到一秒的时间内执行:

    select PropertyID from msa_GetPropertlyListWithNoMessages_TVF(DATEADD(hh, -2, Getdate())) 
    

    此语句在 5 小时后从未完成执行:

    declare @msg_age as Datetime
    SET @msg_age = DATEADD(hh, -2, Getdate())
    select PropertyID from msa_GetPropertlyListWithNoMessages_TVF(@msg_age)
    

    在第二个调用中添加 OPTION (RECOMPILE) 可以解决问题。

    据我所知,使用 datetime 参数会产生截然不同的执行计划。我很想知道原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      • 2011-11-29
      相关资源
      最近更新 更多