在视图中使用呼叫getDate()是否会始终如一地比直接使用getDate()的性能更差?

发布于 2025-02-11 07:12:45 字数 505 浏览 1 评论 0 原文

我的功能可以在过去/将来获得本周的星期一 @x 周。我从本网站上的其他代码中将其固定在一起。我相信这是这样的:

CREATE FUNCTION [FOO]
    (@X INT)
RETURNS DATE
AS
BEGIN
    RETURN DATEADD(WEEK, @X, DATEADD(d, -((DATEPART(DW, GETDATE()))
END

我最近发现,如果我在视图中调用此功能,那么我的性能会比复制上述代码并粘贴上述代码的性能要差。换句话说,我发现直接使用 cast(dateAdd(date,[x value onder],dateadd(d, - ((datepart(ddw,getdate()),日期)要远。 ]

性能比 foo([x值 的视图时,我的用户定义的功能很多。

使用用户定义的功能;当我尝试查询任何使用该行为 ()始终是一个坏主意。

我检查了任何类型的不匹配。

I have a function that gets the Monday of the week @X weeks in the past/future. I bolted it together from other code on this website. I believe it goes like this:

CREATE FUNCTION [FOO]
    (@X INT)
RETURNS DATE
AS
BEGIN
    RETURN DATEADD(WEEK, @X, DATEADD(d, -((DATEPART(DW, GETDATE()))
END

I've recently found that if I call this function inside of a view, then I get dramatically worse performance than if I copy and pasted the above code instead. In other words, I find that directly using CAST(DATEADD(WEEK, [X VALUE HERE], DATEADD(d, -((DATEPART(DW, GETDATE())) AS DATE) to be far more performant than using FOO([X VALUE HERE]).

If the activity monitor is to be trusted, it's as if the value of GETDATE() is being forgotten when you use the user-defined function; I see my user-defined function being called a great many times when I try to query any views that use it.

Is there any known cause for this behavior? It's as if making functions with GETDATE() is always a bad idea. This question hints towards as much, but it's not a direct answer.

I've checked for any type mismatches of any sort. There is none. @@VERSION reports that I'm on a 2016 version.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再可℃爱ぅ一点好了 2025-02-18 07:12:45

这一切都在此SQLServer 2019文章中解释了: https://learn.microsoft.com/en-us/sql/sql/relational-databases/user-defined-functions/scalar-udf-inlining?view? Ver15 。正如@JereenMostert所解释的那样,除非您有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 应用或子查询来调用。

This is all explained in this SqlServer 2019 article: https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/scalar-udf-inlining?view=sql-server-ver15. As @JeroenMostert explained, unless you have v2019 or later and can meet all of the requirements, Scalar UDFs tend to suck performance-wise.

The only way around this prior to v2019 would be to change it into an inline Table-valued Function (iTVF) instead. These use the following syntax:

-- 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 [ ) ]
[ ; ]

And then would have to be invoked with a JOIN, APPLY or subquery.

漫漫岁月 2025-02-18 07:12:45

@j.mini,您说:“好像用 getDate()始终是一个坏主意一样”。

它与 getDate()无关。它涉及2019年以前SQL Server中的任何用户定义的标量功能。2019年之前的SQL Server中的任何用户定义的标量功能都是一个坏主意,因为性能可能很差。当您的代码运行10倍或100倍时,用户会注意到。

这使标准编程成语“如果您看到自己多次做同样的事情,那么在T-SQL中使其成为一个好名字的功能”。

其他RDBMS(例如Postgres和Oracle)的行为可能会有所不同,并且在用户定义的功能方面的性能非常好。

这只是您需要了解的SQL Server的“功能”(或者是特殊性)。特别是因为您在多个位置使用此功能。所有这些地方(查询)可能比以前要慢得多。

这是亚伦·伯特兰德(Aaron Bertrand)的一篇很好的文章,内容涉及:

@J.Mini, you said "as if making functions with GETDATE() is always a bad idea".

It is not about the GETDATE(). It is about any user-defined scalar function in SQL Server prior to 2019. Any user-defined scalar function in SQL Server prior to 2019 is a bad idea because of likely poor performance. When your code runs 10x or 100x slower your users will notice.

This makes the standard programming idiom "if you see yourself doing the same thing many times, then make it a function with a good name" to be a bad idea in T-SQL.

Other RDBMSs like Postgres and Oracle may behave differently and work perfectly fine performance-wise with user-defined functions.

It is just a "feature" (or, rather, a peculiarity) of SQL Server that you need to be aware of. Especially since you use this function in multiple places. All of these places (queries) are likely much slower than they could have been.

Here is a good article by Aaron Bertrand on this topic:

Encapsulating Common Code Into Scalar UDFs

初熏 2025-02-18 07:12:45

每当您将getDate()作为行级行集的一部分时,您的结果就会在越多的行时速度较慢。这是因为每个行都调用功能。几乎不需要这一点,因为您可能不需要每个单独的行的精确度。取而代之的是,在进行任何数据查询之前,请声明一个称为@nowdate的变量,并在开始时使用getDate()填写。然后,现在您可以在查询中使用getDate()的任何地方都可以用nowdate()替换。您会看到重大的表现增长。

Anytime you use GetDate() as part of a row level rowset, your result is going to be dramatically slower the more rows you have. That is because the function is being called for every row. This is almost never needed since the you likely don't need precision of seconds for each separate row. Instead, prior to any query of data, declare a variable called @NowDate and fill it at the beginning with GetDate(). Then, everywhere you would have used GetDate() in the query can now be replaced with NowDate(). You will see a MAJOR performance gain.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文