Ahm*_*tun 4 sql sql-server dateadd
我在Sql Server 2008上有这样的查询:
DECLARE @START_DATE DATETIME
SET @START_DATE = GETDATE()
SELECT * FROM MY_TABLE
WHERE TRANSACTION_DATE_TIME > DATEADD(MINUTE, -1440, @START_DATE)
Run Code Online (Sandbox Code Playgroud)
在上面看到的select查询中,SqlServer是否优化查询以便不再一次计算DATEADD结果.或者我自己有责任将DATEADD结果存储在临时变量上?
Rem*_*anu 10
被视为运行时常量的SQL Server函数仅评估一次.GETDATE()是一个这样的函数,DATEADD(..., constant, GETDATE())也是一个运行时常量.通过在查询中保留实际函数调用,您可以让优化器查看实际使用的值(而不是变量值嗅探),然后它可以相应地调整其基数估计,从而可能提出更好的计划.
另请阅读:查询差查询性能:基数估计期间的常量折叠和表达式评估.
@Martin Smith
您可以运行此查询:
set nocount on;
declare @known int;
select @known = count(*) from sysobjects;
declare @cnt int = @known;
while @cnt = @known
select @cnt = count(*) from sysobjects where getdate()=getdate()
select @cnt, @known;
Run Code Online (Sandbox Code Playgroud)
在我的情况下,在22秒后,它击中了边界情况,循环退出.重要的是循环退出@cnt 零.可以预期,如果getdate()每行进行评估,那么我们将得到@cnt与正确的@known计数不同,但不是0.当循环存在时@cnt为零的事实表明每个getdate()被评估一次,然后是相同的常量值用于每行WHERE过滤(匹配无).我知道一个正面的例子并不能证明一个定理,但我认为这个案例已经足够确凿.
令人惊讶的是,我发现使用GETDATE()内联似乎比预先执行此类计算更有效.
DECLARE @sd1 DATETIME, @sd2 DATETIME;
SET @sd1 = GETDATE();
SELECT * FROM dbo.table
WHERE datetime_column > DATEADD(MINUTE, -1440, @sd1)
SELECT * FROM dbo.table
WHERE datetime_column > DATEADD(MINUTE, -1440, GETDATE())
SET @sd2 = DATEADD(MINUTE, -1440, @sd1);
SELECT * FROM dbo.table
WHERE datetime_column > @sd2;
Run Code Online (Sandbox Code Playgroud)
如果您检查这些计划,中间查询将始终以最低成本(但不总是最低经过时间).当然,它可能取决于您的索引和数据,并且您不应基于一个查询做出任何假设,即相同的优先级优化将对另一个查询起作用.我的本能是不进行任何内联计算,而是使用@sd2上面的变化...但我已经知道我不能完全信任我的直觉而且我不能根据我在特殊情况.