Le mécanisme derrière la sargabilité du casting à ce jour est appelé recherche dynamique .
SQL Server appelle une fonction interne GetRangeThroughConvert
pour obtenir le début et la fin de la plage.
De manière quelque peu surprenante, ce n'est pas la même plage que vos valeurs littérales.
Création d'un tableau avec une ligne par page et 1440 lignes par jour
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
Puis courir
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 première requête a 1443
lu et la seconde 2883
, il lit un jour supplémentaire puis le rejette contre un prédicat résiduel.
Le plan montre que le prédicat de recherche est
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
Ainsi, au lieu de >= '20130101' ... < '20130102'
le lire, > '20121231' ... < '20130102'
puis élimine toutes les 2012-12-31
lignes.
Le fait que les estimations de cardinalité ne soient pas aussi précises que dans le cas d’une interrogation de distance classique présente un autre inconvénient. Cela se voit dans une version modifiée de votre SQL Fiddle .
Les 100 lignes de la table correspondent maintenant au prédicat (avec des dates-heures distantes d'une minute le même jour).
La deuxième requête (plage) estime correctement que 100 correspondra et utilisera une analyse d'index en cluster. La CAST( AS DATE)
requête estime à tort qu'une seule ligne correspondra et produit un plan avec des recherches de clé.
Les statistiques ne sont pas complètement ignorées. Si toutes les lignes de la table ont la même chose datetime
et si elles correspondent au prédicat (par exemple 20130101 00:00:00
ou 20130101 01:00:00
), le plan affiche une analyse d'index en cluster avec environ 31,6228 lignes.
100 ^ 0.75 = 31.6228
Donc, dans ce cas, il apparaît que l'estimation est dérivée de la formule ici .
Si toutes les lignes de la table ont la même chose datetime
et si elles ne correspondent pas au prédicat (par exemple 20130102 01:00:00
), alors le nombre de lignes estimé est égal à 1 et le plan contient des recherches.
Dans les cas où la table a plusieurs DISTINCT
valeurs, les lignes estimées semblent être les mêmes que si la requête cherchait exactement 20130101 00:00:00
.
Si l'histogramme des statistiques comporte un pas, 2013-01-01 00:00:00.000
l'estimation est basée sur le EQ_ROWS
(c'est-à-dire qu'elle ne tient pas compte des autres heures à cette date). Sinon, s'il n'y a pas d'étape, il semblerait que vous utilisiez les AVG_RANGE_ROWS
étapes précédentes.
Comme datetime
avec une précision d'environ 3 ms dans de nombreux systèmes, il y aura très peu de valeurs de doublons réelles et ce nombre sera égal à 1.