getdate()
é um tempo de execução função constante
e é avaliado apenas uma vez por referência de função e é por isso que SELECT GETDATE()
FROM SomeBigTable
retornará o mesmo resultado para todas as linhas, independentemente de quanto tempo a consulta demore para ser executada.
Há uma diferença entre os dois no entanto. Como o primeiro usa uma variável e o plano é compilado antes que a variável seja atribuída ao SQL Server (na ausência de uma recompilação) assumirá que 30% das linhas serão retornadas. Essa suposição pode fazer com que ele use um plano diferente da segunda consulta.
Algo a ter em mente ao usar
GETDATE()
diretamente em um filtro é que ele avalia GETDATE()
em tempo de compilação e, posteriormente, é possível que a seletividade mude drasticamente sem que a consulta ou os dados sejam alterados para acionar uma recompilação. No exemplo abaixo em relação a uma tabela de 1.000 linhas, a consulta usando uma variável leva a um plano com uma estimativa de 300 linhas e uma verificação completa da tabela, enquanto a consulta com a chamada de função incorporada estima 1 linha e faz uma pesquisa de marcador. Isso é preciso na primeira execução, mas na segunda execução, devido à passagem do tempo, todas as linhas se qualificam e acaba fazendo 1.000 pesquisas aleatórias. 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]