43

更好,我的意思是它会以非边际量提高性能吗?

也就是说,我每次调用GETDATE(),服务器返回那个值需要做多少工作

如果我GETDATE()在存储过程的许多地方使用,我是否应该创建一个变量来存储事务的日期?

declare @transDate datetime = GETDATE()

基准数据会很棒。

编辑我想澄清一下:我主要对这两种可能性之间的实际性能差异以及它是否重要感兴趣。

4

5 回答 5

24

[注意:如果您要否决这个答案,请发表评论解释原因。它已经被否决了很多次,最后 ypercube(谢谢)至少解释了一个原因。我无法删除答案,因为它已被接受,因此您不妨帮助改进它。]

根据微软的这个交流,GETDATE()从查询中的常量切换到 SQL Server 2005 中的非确定性。回想起来,我认为这并不准确。我认为它在 SQL Server 2005 之前完全是非确定性的,然后自 SQL Server 2005 起侵入了一种称为“非确定性运行时常量”的东西。后面的短语似乎真的意味着“查询中的常量”。

(并且GETDATE()被定义为明确且自豪的非确定性,没有限定词。)

唉,在 SQL Server 中,非确定性并不意味着对每一行都评估一个函数。SQL Server 确实使这变得不必要的复杂和模棱两可,几乎没有关于该主题的文档。

实际上,函数调用是在查询运行时评估的,而不是在编译查询时评估一次,并且每次调用它的值都会改变。在实践中,GETDATE()只对使用它的每个表达式进行一次评估——在执行时而不是编译时。但是,Microsoft 将rand()getdate()归入一个特殊类别,称为非确定性运行时常量函数。相比之下,Postgres 不会跳过这样的环节,它只是调用在“稳定”执行时具有恒定值的函数。

尽管有 Martin Smith 的评论,但 SQL Server 文档在这个问题上根本没有明确说明——GETDATE()被描述为“非确定性”和“非确定性运行时常量”,但该术语并没有真正解释。 例如,我在一个地方找到了术语,文档中的下一行说不要在子查询中使用非确定性函数。对于“非确定性运行时常数”,这将是愚蠢的建议。

我建议即使在查询中也使用带有常量的变量,这样您就有了一致的值。这也使意图非常明确:您需要查询中的单个值。在单个查询中,您可以执行以下操作:

select . . . 
from (select getdate() as now) params cross join
     . . . 

实际上,这是一个只在查询中评估一次的建议,但可能会有例外。由于在所有不同的行上返回相同的值,所以会出现混淆getdate()——但它可以在不同的列中返回不同的值。每个表达式getdate()都被独立评估。如果您运行,这很明显:

select rand(), rand()
from (values (1), (2), (3)) v(x);

在存储过程中,您可能希望变量中有一个值。如果存储过程在午夜过去时运行,并且日期发生变化,会发生什么情况?这对结果有什么影响?

至于性能,我的猜测是日期/时间查找是最小的,并且当查询开始运行时,每个表达式都会发生一次查询。这不应该是真正的性能问题,而更多的是代码一致性问题。

于 2012-08-22T17:51:37.667 回答
18

我的建议是使用变量,主要是因为如果您有一个长时间运行的进程,GetDate()调用之间的值可能会有所不同。

除非您只使用其中的Date一部分,GetDate()否则您将确保您始终使用相同的值。

于 2012-08-22T17:20:12.147 回答
3

使用带有getdate()或类似函数的变量的一个原因suser_sname()是,如果您正在插入行,或者如果您正在执行GROUP BY. 如果您插入大量行,您会注意到这一点。

我自己将 300GB 的数据迁移到多个表时遇到了这种情况。

于 2016-02-25T00:28:35.230 回答
2

我正在使用 GETDATE() 函数作为 SP 中的变量来测试几个存储过程,并且由于查询优化器不知道操作读取此存储的值是什么,我的 IO 读取和执行时间增加了带有参数、变量和文字的过程执行,也就是说,您可以在 SP 的每个部分中使用 GETDATE() 函数,因为@Gordon Linoff提到它的值在执行期间不会改变,或者为了避免/消除这样的想法值可能会改变我确实以这种方式创建了一个参数:

CREATE PROC TestGetdate
(
@CurrentDate DATETIME = NULL
)
AS
SET CurrentDate  = GETDATE()

.....然后使用你认为合适的参数,你会看到好的结果

欢迎任何意见或建议。

于 2017-05-25T15:30:05.547 回答
0

我用了

WHERE ActualDateShipped+30 > dbo.Today()

结合下面的功能。将我的查询时间从 13 秒缩短到 2 秒。这篇文章中没有先前的答案帮助 SQL 2008/R2 中的这个问题。

CREATE FUNCTION [dbo].[Today]()

    RETURNS date
    AS
    BEGIN

        DECLARE @today date = getdate()

        RETURN @today
    End
于 2016-09-09T01:00:34.453 回答