sql >> Base de Datos >  >> RDS >> Sqlserver

¿Alguien podría explicar la diferencia entre dos consultas?

getdate() es un tiempo de ejecución función constante y solo se evalúa una vez por referencia de función, por lo que

SELECT GETDATE()
FROM SomeBigTable

devolverá el mismo resultado para todas las filas, independientemente del tiempo que tarde en ejecutarse la consulta.

Hay una diferencia entre los dos sin embargo. Como el primero usa una variable y el plan se compila antes de que la variable se asigne a SQL Server (en ausencia de una recompilación) supondrá que se devolverá el 30% de las filas. Esta conjetura puede hacer que use un plan diferente al de la segunda consulta.

Algo a tener en cuenta al usar GETDATE() directamente en un filtro es que evalúa GETDATE() en el momento de la compilación y posteriormente, es posible que la selectividad cambie drásticamente sin que la consulta o los datos cambien para desencadenar una recompilación. En el siguiente ejemplo, en una tabla de 1000 filas, la consulta que usa una variable conduce a un plan con un estimado de 300 filas y un escaneo completo de la tabla, mientras que la consulta con la llamada de función incrustada estima 1 fila y realiza una búsqueda de marcadores. Esto es correcto en la primera ejecución, pero en la segunda, debido al paso del tiempo, todas las filas califican y termina realizando 1000 búsquedas aleatorias.

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]