Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

La requête s'exécute lentement avec l'expression de date, mais rapidement avec un littéral de chaîne

Cela pourrait mieux fonctionner :

Where FK.DT = cast(getdate() + 1 - datepart(day, getdate()) as date)

Sauf si vous exécutez avec l'indicateur de trace 4199, il y a un bogue qui affecte les estimations de cardinalité. Au moment de la rédaction

SELECT DATEADD(m, DATEDIFF(m, getdate(), 0), 0), 
       DATEADD(m, DATEDIFF(m, 0, getdate()), 0)

Retours

+-------------------------+-------------------------+
| 1786-06-01 00:00:00.000 | 2013-08-01 00:00:00.000 |
+-------------------------+-------------------------+

Le bogue est que le prédicat dans la question utilise la première date plutôt que la seconde lors de la dérivation des estimations de cardinalité. Donc pour la configuration suivante.

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)

Requête 1

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

Estime que le nombre de lignes correspondantes sera de 100 000. C'est le numéro qui correspond à la date '1786-06-01' .

Mais les deux requêtes suivantes

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)

Donnez ce plan

En raison des estimations de cardinalité beaucoup plus précises, le plan effectue désormais une seule recherche d'index plutôt qu'une analyse complète.