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 GetRangeThroughConvert
para 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 1443
lecturas y la segunda, 2883
por 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-31
filas.
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 datetime
y coincide con el predicado (por ejemplo, 20130101 00:00:00
o 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 datetime
y 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 DISTINCT
valor, 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.000
entonces 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_ROWS
de los pasos circundantes.
Como datetime
tiene una precisión de aproximadamente 3 ms en muchos sistemas, habrá muy pocos valores duplicados reales y este número será 1.