更好,我的意思是它会以非边际量提高性能吗?
也就是说,我每次调用GETDATE()
,服务器返回那个值需要做多少工作?
如果我GETDATE()
在存储过程的许多地方使用,我是否应该创建一个变量来存储事务的日期?
declare @transDate datetime = GETDATE()
基准数据会很棒。
编辑我想澄清一下:我主要对这两种可能性之间的实际性能差异以及它是否重要感兴趣。
更好,我的意思是它会以非边际量提高性能吗?
也就是说,我每次调用GETDATE()
,服务器返回那个值需要做多少工作?
如果我GETDATE()
在存储过程的许多地方使用,我是否应该创建一个变量来存储事务的日期?
declare @transDate datetime = GETDATE()
基准数据会很棒。
编辑我想澄清一下:我主要对这两种可能性之间的实际性能差异以及它是否重要感兴趣。
[注意:如果您要否决这个答案,请发表评论解释原因。它已经被否决了很多次,最后 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);
在存储过程中,您可能希望变量中有一个值。如果存储过程在午夜过去时运行,并且日期发生变化,会发生什么情况?这对结果有什么影响?
至于性能,我的猜测是日期/时间查找是最小的,并且当查询开始运行时,每个表达式都会发生一次查询。这不应该是真正的性能问题,而更多的是代码一致性问题。
我的建议是使用变量,主要是因为如果您有一个长时间运行的进程,GetDate()
调用之间的值可能会有所不同。
除非您只使用其中的Date
一部分,GetDate()
否则您将确保您始终使用相同的值。
使用带有getdate()
或类似函数的变量的一个原因suser_sname()
是,如果您正在插入行,或者如果您正在执行GROUP BY
. 如果您插入大量行,您会注意到这一点。
我自己将 300GB 的数据迁移到多个表时遇到了这种情况。
我正在使用 GETDATE() 函数作为 SP 中的变量来测试几个存储过程,并且由于查询优化器不知道操作读取此存储的值是什么,我的 IO 读取和执行时间增加了带有参数、变量和文字的过程执行,也就是说,您可以在 SP 的每个部分中使用 GETDATE() 函数,因为@Gordon Linoff提到它的值在执行期间不会改变,或者为了避免/消除这样的想法值可能会改变我确实以这种方式创建了一个参数:
CREATE PROC TestGetdate
(
@CurrentDate DATETIME = NULL
)
AS
SET CurrentDate = GETDATE()
.....然后使用你认为合适的参数,你会看到好的结果
欢迎任何意见或建议。
我用了
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