El mecanismo detrás de la sargabilidad del casting hasta la fecha se llama búsqueda dinámica .
SQL Server llama a una función interna GetRangeThroughConvertpara obtener el inicio y el final del rango.
Sorprendentemente, este no es el mismo rango que sus valores literales.
Crear una tabla con una fila por página y 1440 filas por día
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
Entonces corriendo
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 primera consulta tiene 1443lecturas y la segunda, 2883por lo que lee un día adicional completo y luego la descarta contra un predicado residual.
El plan muestra que el predicado de búsqueda es
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
Entonces, en lugar de >= '20130101' ... < '20130102'leer, > '20121231' ... < '20130102'luego descarta todas las 2012-12-31filas.
Otra desventaja de confiar en él es que las estimaciones de cardinalidad pueden no ser tan precisas como con la consulta de rango tradicional. Esto se puede ver en una versión modificada de su SQL Fiddle .
Las 100 filas de la tabla ahora coinciden con el predicado (con fecha y hora con 1 minuto de diferencia, todo en el mismo día).
La segunda consulta (rango) estima correctamente que 100 coincidirán y utiliza un escaneo de índice agrupado. La CAST( AS DATE)consulta estima incorrectamente que solo una fila coincidirá y produce un plan con búsquedas clave.
Las estadísticas no se ignoran por completo. Si todas las filas de la tabla tienen el mismo datetimey coincide con el predicado (por ejemplo, 20130101 00:00:00o 20130101 01:00:00), el plan muestra un análisis de índice agrupado con un estimado de 31.6228 filas.
100 ^ 0.75 = 31.6228
Entonces, en ese caso, parece que la estimación se deriva de la fórmula aquí .
Si todas las filas de la tabla tienen el mismo datetimey no coincide con el predicado (p 20130102 01:00:00. Ej. ), Vuelve al recuento de filas estimado de 1 y al plan con búsquedas.
Para los casos en que la tabla tiene más de un DISTINCTvalor, las filas estimadas parecen ser las mismas que si la consulta estuviera buscando exactamente 20130101 00:00:00.
Si el histograma de estadísticas tiene un paso, 2013-01-01 00:00:00.000entonces la estimación se basará en EQ_ROWS(es decir, sin tener en cuenta otras veces en esa fecha). De lo contrario, si no hay un paso, parece que usa el AVG_RANGE_ROWSde los pasos circundantes.
Como datetimetiene una precisión de aproximadamente 3 ms en muchos sistemas, habrá muy pocos valores duplicados reales y este número será 1.