Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Alguém poderia explicar a diferença entre duas consultas?


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]