我有一个函数可以获取过去/ future 周 @X
周的星期一。我将它与本网站上的其他代码结合在一起。我相信它是这样的:
CREATE FUNCTION [FOO]
(@X INT)
RETURNS DATE
AS
BEGIN
RETURN DATEADD(WEEK, @X, DATEADD(d, -((DATEPART(DW, GETDATE()))
END
我最近发现,如果我在一个 View 中调用这个函数,那么我得到的性能比我复制和粘贴上面的代码要差得多。换句话说,我发现直接使用 CAST(DATEADD(WEEK, [X VALUE HERE], DATEADD(d, -((DATEPART(DW, GETDATE())) AS DATE)
会很远比使用 FOO([X VALUE HERE])
性能更高。
如果要信任事件监视器,那么当您使用用户定义的函数时就好像忘记了 GETDATE()
的值;当我尝试查询使用它的任何 View 时,我发现我的用户定义函数被调用了很多次。
此行为是否有任何已知原因?就好像用 GETDATE()
做函数总是一个坏主意。 This question有很多暗示,但这不是直接的答案。
我已经检查了任何类型的任何类型不匹配。空无一人。 @@VERSION
报告我使用的是 2016 版本。
最佳答案
这篇 SqlServer 2019 文章对此进行了全部解释:https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/scalar-udf-inlining?view=sql-server-ver15 .正如@JeroenMostert 所解释的那样,除非您拥有 v2019 或更高版本并且可以满足所有要求,否则标量 UDF 往往会在性能方面表现不佳。
在 v2019 之前解决此问题的唯一方法是改为将其更改为内联表值函数 (iTVF)。它们使用以下语法:
-- Transact-SQL Inline Table-Valued Function Syntax
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [ READONLY ] }
[ ,...n ]
]
)
RETURNS TABLE
[ WITH <function_option> [ ,...n ] ]
[ AS ]
RETURN [ ( ] select_stmt [ ) ]
[ ; ]
然后必须使用 JOIN
、APPLY
或子查询来调用。
关于sql-server - 在 View 中使用调用 GETDATE() 的函数是否始终比直接使用 GETDATE() 提供更差的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72788519/