В SQL Server 2008 был добавлен тип данных даты .
Кастинг datetime
столбца date
является sargable и может использовать индекс на datetime
колонке.
select *
from T
where cast(DateTimeCol as date) = '20130101';
Другой вариант - использовать диапазон.
select *
from T
where DateTimeCol >= '20130101' and
DateTimeCol < '20130102'
Являются ли эти запросы одинаково хорошими или один предпочтительнее другого?
sql-server
Микаэль Эрикссон
источник
источник
where cast(date_column as date) = 'value'
когда представлен с C # аналогичноwhere obj.date_column.Date == date_variable
.Ответы:
Механизм, обеспечивающий гибкость кастинга на сегодняшний день, называется динамическим поиском .
SQL Server вызывает внутреннюю функцию,
GetRangeThroughConvert
чтобы получить начало и конец диапазона.Несколько удивительно, что это не тот же диапазон, что и ваши буквальные значения.
Создание таблицы со строкой на страницу и 1440 строк в день
Потом работает
Первый запрос имеет
1443
чтение, а второй2883
- чтение всего дополнительного дня, а затем отбрасывает его против остаточного предиката.План показывает, что предикат поиска
Таким образом, вместо
>= '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 строками.Таким образом, в этом случае, как представляется, оценка выводится из формулы здесь .
Если все строки в таблице имеют одинаковые значения
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.источник
TL;DR
деталь с несколькими пунктами в разных случаях, добавив, будет ли в этом случае приведение актеров на сегодняшний день - это хорошая идея или нет?Я знаю, что у этого есть давний Великий Ответ® от Мартина, но я хотел добавить некоторые изменения в поведение здесь в более новых версиях SQL Server. Похоже, это было проверено только до 2008R2.
С новыми подсказками USE, которые делают возможным некоторое путешествие во времени для оценки количества элементов , мы можем видеть, когда что-то изменилось.
Используя ту же настройку, что и в скрипте SQL.
Мы можем протестировать разные уровни следующим образом:
Планы на все это доступны здесь . Уровни Compat 100 и 110 дают план поиска ключа, но начиная с уровня Compat 120, мы начинаем получать один и тот же план сканирования с оценками в 100 строк. Это верно до уровня 140 соотечественника.
Оценка количества кардинальных
>= '20130101', < '20130102'
планов остается на уровне 100, что и ожидалось.источник