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

A consulta é lenta com expressão de data, mas rápida com literal de string


Isso poderia funcionar melhor:
Where FK.DT = cast(getdate() + 1 - datepart(day, getdate()) as date)

A menos que você esteja executando com o sinalizador de rastreamento 4199 ativado, há um bug que afeta as estimativas de cardinalidade. Na hora de escrever
SELECT DATEADD(m, DATEDIFF(m, getdate(), 0), 0), 
       DATEADD(m, DATEDIFF(m, 0, getdate()), 0)

Devoluções
+-------------------------+-------------------------+
| 1786-06-01 00:00:00.000 | 2013-08-01 00:00:00.000 |
+-------------------------+-------------------------+

O bug é que o predicado na pergunta usa a primeira data em vez da segunda ao derivar as estimativas de cardinalidade. Então, para a seguinte configuração.
CREATE TABLE FK
(
ID INT IDENTITY PRIMARY KEY,
DT DATE,
Filler CHAR(1000) NULL,
UNIQUE (DT,ID)
)

INSERT INTO FK (DT)
SELECT TOP (1000000) DATEADD(m, DATEDIFF(m, getdate(), 0), 0)
FROM master..spt_values o1, master..spt_values o2
UNION ALL
SELECT               DATEADD(m, DATEDIFF(m, 0, getdate()), 0)

Consulta 1

SELECT COUNT(Filler)
FROM FK
WHERE FK.DT = CAST(DATEADD(m, DATEDIFF(m, 0, getdate()), 0) AS DATE)  



Estima que o número de linhas correspondentes será de 100.000. Este é o número que corresponde à data '1786-06-01' .

Mas ambas as consultas a seguir
SELECT COUNT(Filler)
FROM FK
WHERE FK.DT = CAST(GETDATE() + 1 - DATEPART(DAY, GETDATE()) AS DATE)

SELECT COUNT(Filler)
FROM FK
WHERE FK.DT = CAST(DATEADD(m, DATEDIFF(m, 0, getdate()), 0) AS DATE)  
OPTION (QUERYTRACEON 4199)

Dê este plano



Devido às estimativas de cardinalidade muito mais precisas, o plano agora faz apenas uma busca de índice único em vez de uma varredura completa.