我在SQL Server中有一个表值函数的奇怪问题(请参阅下面的代码)。当我在函数中注释掉CONVERT(INT, DATEDIFF(...))
行时,结果几乎是瞬间完成的。当我取消注释它时,它在2018-02-28的日期运行有点慢(~7秒),在2018-03-31的日期运行非常慢(超过一分钟)。
qryLMPDATE
返回一行表。可能导致此问题的原因是什么?一种想法是lmpdate
等于2018-02-28中的valdate
,但是在2018-03-31,lmpdate
与valdate
不同。因此,查询处理器可能无效地计算这些值。
为了提供更多上下文,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
);
答案 0 :(得分:1)
查看该计划,似乎是因为您正在[ActuarialDW].[IFE].[tblFIAResvFeat]
上进行表扫描,我怀疑它是在ife.qryLMPDATE函数中查询的。我怀疑你没有[ValDate]
的索引。基本上,您的查询是扫描整个表,查找[ValDate]='2018-03-31 00:00:00.000'
的值,它可以使用索引查找来加快速度。表越大,花费的时间越长等等。这占用了查询成本的95%...所以我从这里开始添加一些索引并重新测试。