sql >> Databasteknik >  >> RDS >> Sqlserver

Frågan går långsamt med datumuttryck, men snabbt med bokstavlig sträng

Detta skulle kunna fungera bättre:

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

Om du inte kör med spårningsflagga 4199 på finns en bugg som påverkar kardinalitetsuppskattningarna. I skrivande stund

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

Retur

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

Problemet är att predikatet i frågan använder det första datumet snarare än det andra när man härleder kardinalitetsuppskattningarna. Så för följande inställningar.

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)

Fråga 1

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

Beräknar att antalet matchande rader kommer att vara 100 000. Detta är numret som matchar datumet '1786-06-01' .

Men båda följande frågor

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)

Ge den här planen

På grund av de mycket mer exakta kardinalitetsberäkningarna gör planen nu bara en enda indexsökning snarare än en fullständig genomsökning.



  1. Fjäderdatafråga för localdate returnerar felaktiga poster - minus en dag

  2. Skapa SQL Server 2012-databas kompatibel för 2008

  3. Hur visar jag ett MySQL-fel i PHP för en lång fråga som beror på användarens input?

  4. Varför visar COUNT() bara en rad i tabellen?