getdate()
е време за изпълнение постоянна функция
и се оценява само веднъж за препратка към функция, поради което
SELECT GETDATE()
FROM SomeBigTable
ще върне един и същ резултат за всички редове, независимо колко време отнема изпълнението на заявката.
Между двете обаче има разлика. Тъй като първият използва променлива и планът се компилира преди променливата да бъде присвоена на SQL Server (при липса на повторно компилиране) ще приеме, че 30% от редовете ще бъдат върнати. Това предположение може да го накара да използва различен план от второто запитване.
Нещо, което трябва да имате предвид при използването на GETDATE()
директно във филтър е, че той оценява GETDATE()
по време на компилиране и след това е възможно селективността да се промени драстично, без нито заявката, нито данните да се променят, за да задействат повторно компилиране. В примера по-долу срещу таблица с 1000 реда заявката, използваща променлива, води до план с приблизително 300 реда и пълно сканиране на таблица, докато заявката с вградено извикване на функция оценява 1 ред и прави търсене на отметки. Това е точно при първото изпълнение, но при второто изпълнение поради изтичането на времето сега всички редове се квалифицират и в крайна сметка се извършват 1000 такива произволни търсения.
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]