使用DATEDIFF函数

时间:2018-04-11 20:07:36

标签: sql sql-server performance

我在SQL Server中有一个表值函数的奇怪问题(请参阅下面的代码)。当我在函数中注释掉CONVERT(INT, DATEDIFF(...))行时,结果几乎是瞬间完成的。当我取消注释它时,它在2018-02-28的日期运行有点慢(~7秒),在2018-03-31的日期运行非常慢(超过一分钟)。

qryLMPDATE返回一行表。可能导致此问题的原因是什么?一种想法是lmpdate等于2018-02-28中的valdate,但是在2018-03-31,lmpdatevaldate不同。因此,查询处理器可能无效地计算这些值。

为了提供更多上下文,lmpdate本质上是一个常数。任何帮助将不胜感激。

ALTER FUNCTION [ife].[qryFoo](@valdate DATETIME)
RETURNS TABLE
     RETURN
         SELECT 
             pol.*,
             CONVERT(INT, (DATEDIFF(day, pol.[RESP_PRIM_DOB], ql.lmpdate) / 365)) AS AttainedAge
         FROM
             (ife.tblFIAResvPol AS pol
         LEFT JOIN 
             ife.qryFeatGLWB(@valdate) AS glwb ON (pol.RESP_CONT = glwb.RESFE_CONT)
                                               AND (pol.ValDate = glwb.ValDate))
         LEFT JOIN 
             ife.qryFeatROP(@valdate) AS qrop ON (pol.RESP_CONT = qrop.RESFE_CONT)
                                              AND (pol.ValDate = qrop.ValDate)
         LEFT JOIN 
             ife.qryLMPDATE(@valdate) AS ql ON pol.ValDate = ql.ValDate
         WHERE
             (((pol.ValDate) = @valdate));

SELECT TOP 2000 * 
FROM ife.qryFoo('2018-02-28');  --takes <1 and 7 seconds, resp.

SELECT TOP 2000 * 
FROM ife.qryFoo('2018-03-31'); --takes <1 and >60 seconds, resp.

修改

可在此处找到查询计划:https://www.brentozar.com/pastetheplan/?id=Bywngenif

这是ife.qryLMPDATE的代码:

ALTER FUNCTION [IFE].[qryLMPDATE](@valdate DATE)
RETURNS TABLE
AS
     RETURN
(
    SELECT TOP 1 @valdate AS valdate,
                 marketdate AS lmpdate
    FROM ife.tblfiaoptionvalue
    WHERE DATEDIFF(day, MarketDate, @valdate) <= 4
);

最新更新

罪魁祸首是IFE.qryLMPDATE。修改函数以使用max()而不是top 1后,性能恢复正常。如果有人可以找到解释,我会将您的答案标记为已接受的答案。

旧代码:

ALTER FUNCTION [IFE].[qryLMPDATE](@valdate DATE)
RETURNS TABLE
AS
     RETURN
(
    SELECT TOP 1 @valdate AS valdate,
                 marketdate AS lmpdate
    FROM ife.tblfiaoptionvalue
    WHERE DATEDIFF(day, MarketDate, @valdate) <= 4
);

新代码:

ALTER FUNCTION [IFE].[qryLMPDATE](@valdate DATE)
RETURNS TABLE
AS
     RETURN
(
    SELECT @valdate AS valdate,
           max(marketdate) AS lmpdate
    FROM ife.tblfiaoptionvalue
    WHERE DATEDIFF(day, MarketDate, @valdate) <= 4
);

1 个答案:

答案 0 :(得分:1)

查看该计划,似乎是因为您正在[ActuarialDW].[IFE].[tblFIAResvFeat]上进行表扫描,我怀疑它是在ife.qryLMPDATE函数中查询的。我怀疑你没有[ValDate]的索引。基本上,您的查询是扫描整个表,查找[ValDate]='2018-03-31 00:00:00.000'的值,它可以使用索引查找来加快速度。表越大,花费的时间越长等等。这占用了查询成本的95%...所以我从这里开始添加一些索引并重新测试。