Mechanizm leżący u podstaw możliwości rzutowania nazywa się dynamicznym wyszukiwaniem .
SQL Server wywołuje funkcję wewnętrzną, GetRangeThroughConvert
aby uzyskać początek i koniec zakresu.
Nieoczekiwanie nie jest to ten sam zakres, co twoje dosłowne wartości.
Tworzenie tabeli z wierszem na stronę i 1440 wierszami dziennie
CREATE TABLE T
(
DateTimeCol DATETIME PRIMARY KEY,
Filler CHAR(8000) DEFAULT 'X'
);
WITH Nums(Num)
AS (SELECT number
FROM spt_values
WHERE type = 'P'
AND number BETWEEN 1 AND 1440),
Dates(Date)
AS (SELECT {d '2012-12-30'} UNION ALL
SELECT {d '2012-12-31'} UNION ALL
SELECT {d '2013-01-01'} UNION ALL
SELECT {d '2013-01-02'} UNION ALL
SELECT {d '2013-01-03'})
INSERT INTO T
(DateTimeCol)
SELECT DISTINCT DATEADD(MINUTE, Num, Date)
FROM Nums,
Dates
Potem biegnie
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT *
FROM T
WHERE DateTimeCol >= '20130101'
AND DateTimeCol < '20130102'
SELECT *
FROM T
WHERE CAST(DateTimeCol AS DATE) = '20130101';
Pierwsze zapytanie zawiera 1443
odczyty, a drugie 2883
odczytuje cały dodatkowy dzień, a następnie odrzuca je względem pozostałego predykatu.
Plan pokazuje, że predykatem wyszukiwania jest
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
Zamiast >= '20130101' ... < '20130102'
tego czyta, > '20121231' ... < '20130102'
a następnie odrzuca wszystkie 2012-12-31
wiersze.
Kolejną wadą polegającą na tym jest to, że szacunki liczności mogą nie być tak dokładne, jak w przypadku tradycyjnego zapytania o zakres. Można to zobaczyć w poprawionej wersji SQL Fiddle .
Wszystkie 100 wierszy w tabeli jest teraz zgodnych z predykatem (z odstępami czasu 1 minuta wszystkie w tym samym dniu).
Drugie zapytanie (zakres) poprawnie szacuje, że 100 będzie pasowało i używa skanowania indeksu klastrowego. CAST( AS DATE)
Zapytania nieprawidłowo szacuje, że tylko jeden wiersz będzie pasował i tworzy plan z najważniejszych wyszukiwań.
Statystyki nie są całkowicie ignorowane. Jeśli wszystkie wiersze w tabeli mają to samo datetime
i pasuje do predykatu (np. 20130101 00:00:00
Lub 20130101 01:00:00
), wówczas plan pokazuje skanowanie indeksu klastrowego z szacowanymi 31,6228 wierszami.
100 ^ 0.75 = 31.6228
Więc w takim przypadku wydaje się, że szacunek pochodzi z formuły tutaj .
Jeśli wszystkie wiersze w tabeli mają to samo datetime
i nie pasuje do predykatu (np. 20130102 01:00:00
), Wówczas wraca do szacowanej liczby wierszy 1 i planu z przeglądami.
W przypadkach, w których tabela ma więcej niż jedną DISTINCT
wartość, szacunkowe wiersze wydają się być takie same, jakby zapytanie szukało dokładnie 20130101 00:00:00
.
Jeśli histogram statystyczny zawiera krok, 2013-01-01 00:00:00.000
wówczas szacunek będzie oparty na EQ_ROWS
(tzn. Nie będzie uwzględniał innych czasów w tym dniu). W przeciwnym razie, jeśli nie ma kroku, wygląda na to, że wykorzystuje AVG_RANGE_ROWS
kroki z otaczających kroków.
Ponieważ datetime
dokładność wynosi około 3 ms w wielu systemach, będzie bardzo niewiele rzeczywistych zduplikowanych wartości, a liczba ta będzie wynosić 1.