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]