getdate()
是runtime constant function,每个函数引用这就是为什么
SELECT GETDATE()
FROM SomeBigTable
将返回相同的结果为所有行无论查询需要多长时间运行只计算一次。
然而,两者之间存在差异。由于第一个使用变量,并且在将变量分配给SQL Server之前编译计划(在没有重新编译的情况下),假定将返回30%的行。这种猜测可能会导致它使用与第二个查询不同的计划。
直接在过滤器中使用GETDATE()
时需要注意的一点是,它在编译时评估GETDATE()
,此后可能在没有查询或数据更改的情况下显着改变选择性以触发重新编译。在下面的示例中,对于1000行表,使用变量的查询会导致计划带有估计的300行和全表扫描,而嵌入函数调用的查询会估计1行并执行书签查找。这在第一次运行时是准确的,但是在第二次运行中,由于时间流逝,现在所有行都有资格,并且最终会执行1,000次这种随机查找。
USE tempdb;
CREATE TABLE [myTable]
(
CreatedDate datetime,
Filler char(8000) NULL
)
CREATE NONCLUSTERED INDEX ix ON [myTable](CreatedDate)
INSERT INTO [myTable](CreatedDate)
/*Insert 1 row that initially qualifies*/
SELECT DATEADD(D,-2001,getdate())
UNION ALL
/*And 999 rows that don't initially qualify*/
SELECT TOP 999 DATEADD(minute,1, DATEADD(D,-2000,getdate()))
FROM master..spt_values
EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT *
FROM [myTable]
WHERE CreatedDate <= @myDate
')
EXEC('
SELECT *
FROM [myTable]
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')
RAISERROR ('Delay',0,1) WITH NOWAIT
WAITFOR DELAY '00:01:01'
EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT *
FROM [myTable]
WHERE CreatedDate <= @myDate
')
EXEC('
SELECT *
FROM [myTable]
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')
DROP TABLE [myTable]
它不计算DATEADD每一行的位置。 在选择甚至开始提取数据之前计算。 – 2012-03-28 10:38:45
相似的问题在这里:http://stackoverflow.com/questions/7301058/does-sql-server-optimize-dateadd-calculation-in-select-query – 2012-03-28 10:45:53