Кастинг на сегодняшний день является мобильным, но это хорошая идея?

В SQL Server 2008 был добавлен дата тип данных.

В этом элементе Connect вы можете увидеть, что при нажатии < code> datetime в date sargable и может использовать индекс на datetime .

  выберите *
от Т
где cast (DateTimeCol как дата) = '20130101';
 

Другой вариант, который у вас есть, - это использовать диапазон.

  выберите *
от Т
где DateTimeCol> = '20130101' и
      DateTimeCol <'20130102'
 

Являются ли эти запросы одинаково хорошими или должны быть предпочтительнее других?

скрипт SQL

43 голоса | спросил Mikael Eriksson 4 FebruaryEurope/MoscowbMon, 04 Feb 2013 11:58:37 +0400000000amMon, 04 Feb 2013 11:58:37 +040013 2013, 11:58:37

1 ответ


52

Механизм застойности литья на сегодняшний день называется динамический поиск .

SQL Server вызывает внутреннюю функцию GetRangeThroughConvert , чтобы получить начало и конец диапазона.

Несколько удивительно, что это не тот же диапазон, что и ваши литералы.

Создание таблицы со строкой на странице и 1440 строк в день

  CREATE TABLE T
  (
     DateTimeCol DATETIME PRIMARY KEY,
     Filler CHAR (8000) DEFAULT 'X'
  );

С Nums (Num)
     AS (номер SELECT
         FROM spt_values
         WHERE type = 'P'
                И число МЕЖДУ 1 И 1440),
     Даты (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'})
ВСТАВИТЬ В Т
            (DateTimeCol)
SELECT DISTINCT DATEADD (MINUTE, Num, Date)
FROM Nums,
       Даты
 

Затем запустите

  SET STATISTICS IO ON;
SET STATISTICS TIME ON;

ВЫБРАТЬ *
FROM T
WHERE DateTimeCol> = '20130101'
       AND DateTimeCol <'20130102'

ВЫБРАТЬ *
FROM T
WHERE CAST (DateTimeCol AS DATE) = '20130101';
 

Первый запрос имеет 1443 и второй 2883 , поэтому он читает целый дополнительный день, а затем отбрасывает его на остаточный предикат.

В плане показан предикат поиска

  Поиск ключей [1]: Начало: DateTimeCol> Скалярный оператор ([Expr1006]),
               Конец: DateTimeCol <Скалярный оператор ([Expr1007])
 

Итак, вместо > = '20130101' ... <'20130102' он читает > '20121231' ... <'20130102' , затем отбрасывает все строки 2012-12-31 .

Другим недостатком полагаться на это является то, что оценки мощности могут быть не такими точными, как при использовании традиционного запроса диапазона. Это можно увидеть в исправленной версии SQL Fiddle .

Все 100 строк в таблице теперь соответствуют предикату (с интервалом времени в одну минуту в один и тот же день).

Второй (диапазон) запрос правильно оценивает, что 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.

ответил Martin Smith 4 FebruaryEurope/MoscowbMon, 04 Feb 2013 14:39:53 +0400000000pmMon, 04 Feb 2013 14:39:53 +040013 2013, 14:39:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132