Механизм, обеспечивающий гибкость кастинга на сегодняшний день, называется динамическим поиском .
SQL Server вызывает внутреннюю функцию, GetRangeThroughConvert
чтобы получить начало и конец диапазона.
Несколько удивительно, что это не тот же диапазон, что и ваши буквальные значения.
Создание таблицы со строкой на страницу и 1440 строк в день
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
Потом работает
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';
Первый запрос имеет 1443
чтение, а второй 2883
- чтение всего дополнительного дня, а затем отбрасывает его против остаточного предиката.
План показывает, что предикат поиска
Seek Keys[1]: Start: DateTimeCol > Scalar Operator([Expr1006]),
End: DateTimeCol < Scalar Operator([Expr1007])
Таким образом, вместо >= '20130101' ... < '20130102'
этого читает, а > '20121231' ... < '20130102'
затем отбрасывает все 2012-12-31
строки.
Другой недостаток - полагаться на то, что оценки мощности могут быть не такими точными, как при традиционном запросе диапазона. Это можно увидеть в исправленной версии вашего SQL Fiddle .
Все 100 строк в таблице теперь соответствуют предикату (с разницей в 1 минуту все в один и тот же день).
Второй (диапазонный) запрос правильно оценивает, что 100 будет соответствовать, и использует сканирование кластерного индекса. CAST( AS DATE)
Запрос неправильно оценивает , что только одна строки будет соответствовать и производит план с ключевым поиском.
Статистика не полностью игнорируется. Если все строки в таблице одинаковы datetime
и соответствуют предикату (например, 20130101 00:00:00
или 20130101 01:00:00
), то план показывает сканирование кластерного индекса с оценочными 31,6228 строками.
100 ^ 0.75 = 31.6228
Таким образом, в этом случае, как представляется, оценка выводится из формулы здесь .
Если все строки в таблице имеют одинаковые значения datetime
и не соответствуют предикату (например 20130102 01:00:00
), тогда он возвращается к оценочному количеству строк, равному 1, и к плану с поисками.
Для случаев, когда таблица имеет более одного DISTINCT
значения, предполагаемые строки выглядят такими же, как если бы запрос выполнялся точно 20130101 00:00:00
.
Если статистическая гистограмма имеет определенный шаг, 2013-01-01 00:00:00.000
тогда оценка будет основана на EQ_ROWS
(то есть, не принимая во внимание другое время на эту дату). В противном случае, если нет шага, это выглядит так, как будто он использует AVG_RANGE_ROWS
окружающие шаги.
Так datetime
как во многих системах точность составляет около 3 мс, фактических повторяющихся значений будет очень мало, и это число будет равно 1.