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