【发布时间】:2018-11-17 20:47:13
【问题描述】:
我最近意识到,通过在子查询中调用 UDF 比直接调用它们执行得更好,为什么会发生这种情况?
举个例子:
CREATE FUNCTION [CurrentYearStart]()
RETURNS DATETIME
AS
BEGIN
DECLARE @Date DATETIME;
SELECT top 1 @Date = StartPeriod
FROM SystemPeriods WITH (NOLOCK);
RETURN @Date;
END
ProviderServiceAreas 有 412585 行。
以下查询在大约 50 秒后返回
SELECT PayGroup, SystemType, MAX(EffDt) AS MaxEffDt
FROM CAT.ProviderServiceAreas
WHERE EffDt > CurrentYearStart()
GROUP BY Paygroup, SystemType
执行计划:https://www.brentozar.com/pastetheplan/?id=BJCom7vgm
以下查询在大约 1s 内返回
SELECT PayGroup, SystemType, MAX(EffDt) AS MaxEffDt
FROM CAT.ProviderServiceAreas
WHERE EffDt > (SELECT CurrentYearStart())
GROUP BY Paygroup, SystemType
【问题讨论】:
-
两者的执行计划是什么?
-
I noticed that by calling the function in the subquery they only execute the function once=> 缓存 :) 无论如何你的函数非常危险(没有 ORDER BY + NOLOCK 的 TOP 1) -
无论如何我都会摆脱这个功能。众所周知,标量函数的性能很差。将其转换为内联表值函数或仅执行子查询。
-
它并不是真正的缓存。这意味着该函数被多次执行并重放缓存的结果。我会想象更多不同的树形,它会评估一次函数,然后将结果用作相关参数。
标签: sql sql-server performance tsql user-defined-functions