Il meccanismo alla base della sargibilità del cast fino ad oggi si chiama ricerca dinamica .
SQL Server chiama una funzione interna GetRangeThroughConvert
per ottenere l'inizio e la fine dell'intervallo.
Un po 'sorprendentemente, questo non è lo stesso intervallo dei tuoi valori letterali.
Creazione di una tabella con una riga per pagina e 1440 righe al giorno
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
Quindi correndo
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';
La prima query ha 1443
letto e la seconda 2883
quindi sta leggendo un intero giorno aggiuntivo, quindi scartandola da un predicato residuo.
Il piano mostra che è il predicato di ricerca
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
Quindi invece di >= '20130101' ... < '20130102'
leggere, > '20121231' ... < '20130102'
quindi scarta tutte le 2012-12-31
righe.
Un altro svantaggio di fare affidamento su di esso è che le stime della cardinalità potrebbero non essere accurate come con l'interrogazione di intervallo tradizionale. Questo può essere visto in una versione modificata del tuo SQL Fiddle .
Tutte le 100 righe nella tabella ora corrispondono al predicato (con intervalli di tempo di 1 minuto l'uno dall'altro tutti nello stesso giorno).
La seconda query (intervallo) stima correttamente che 100 corrisponderà e utilizza una scansione dell'indice cluster. La CAST( AS DATE)
query stima erroneamente che una sola riga corrisponderà e produce un piano con ricerche chiave.
Le statistiche non vengono completamente ignorate. Se tutte le righe nella tabella hanno le stesse datetime
e corrispondono al predicato (ad es. 20130101 00:00:00
O 20130101 01:00:00
), il piano mostra una scansione dell'indice cluster con una stima di 31.6228 righe.
100 ^ 0.75 = 31.6228
Quindi in quel caso sembra che la stima sia derivata dalla formula qui .
Se tutte le righe nella tabella hanno lo stesso datetime
e non corrisponde al predicato (ad es. 20130102 01:00:00
), Allora ricade sul conteggio delle righe stimato di 1 e il piano con ricerche.
Per i casi in cui la tabella ha più di un DISTINCT
valore, le righe stimate sembrano essere le stesse della query esattamente cercata 20130101 00:00:00
.
Se l'istogramma statistico presenta un passaggio, 2013-01-01 00:00:00.000
la stima si baserà sul EQ_ROWS
(ovvero non prendendo in considerazione altre volte in quella data). Altrimenti se non ci sono passaggi sembra che usi i AVG_RANGE_ROWS
passaggi circostanti.
Come datetime
ha una precisione di circa 3 ms in molti sistemi, ci saranno pochissimi valori effettivi duplicati e questo numero sarà 1.