sql >> Database teknologi >  >> RDS >> Sqlserver

Forespørgsel kører langsomt med datoudtryk, men hurtigt med streng literal

Dette kunne fungere bedre:

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

Medmindre du kører med sporingsflag 4199 på, er der en fejl som påvirker kardinalitetsestimaterne. I skrivende stund

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

Returnerer

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

Fejlen er, at prædikatet i spørgsmålet bruger den første dato i stedet for den anden, når kardinalitetsestimaterne udledes. Så for den følgende opsætning.

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)
 

Forespørgsel 1

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

Estimerer, at antallet af matchende rækker vil være 100.000. Dette er det tal, der matcher datoen '1786-06-01' .

Men begge de følgende forespørgsler

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)
 

Giv denne plan

På grund af de meget mere nøjagtige kardinalitetsestimater udfører planen nu kun en enkelt indekssøgning i stedet for en fuld scanning.



  1. Debug PDO mySql indsæt NULL i databasen i stedet for tom

  2. UTF-8-databaseproblem

  3. Hvordan bruger man Oracle-datapumpe-eksportværktøjet til at oprette en dumpfil på den lokale maskine?

  4. Genaktiver SSMS-tilføjelse