Каждая опция, которая включает манипуляции CAST или TRUNCATE или DATEPART в поле datetime, имеет ту же проблему: запрос должен сканировать весь набор результатов (40k), чтобы найти отдельные даты. Производительность может незначительно отличаться между различными реализациями.
Что вам действительно нужно, это иметь индекс, который может дать ответ в мигающем режиме. Вы можете либо иметь постоянный вычисленный столбец с индексом, который (требует изменения структуры таблицы), либо индексированный вид (requires Enterprise Edition for QO to consider the index из коробки).
сохранялось вычисляемый столбец:
alter table foo add date_only as convert(char(8), [datetimecolumn], 112) persisted;
create index idx_foo_date_only on foo(date_only);
индексированных вид:
create view v_foo_with_date_only
with schemabinding as
select id
, convert(char(8), [datetimecolumn], 112) as date_only
from dbo.foo;
create unique clustered index idx_v_foo on v_foo_with_date_only(date_only, id);
Обновление
Для того, чтобы полностью исключить одно сканирование можно было использовать GROUP BY обманом индексированного представления, как это:
create view v_foo_with_date_only
with schemabinding as
select
convert(char(8), [d], 112) as date_only
, count_big(*) as [dummy]
from dbo.foo
group by convert(char(8), [d], 112)
create unique clustered index idx_v_foo on v_foo_with_date_only(date_only)
Запрос select distinct date_only from foo
будет использовать это индексированное представление. По-прежнему сканируется технически, но на уже «отличном» индексе, поэтому проверяются только нужные записи. Я считаю, что это был взлом, я бы не рекомендовал его для живого кода производства.
AFAIK SQL Server не имеет возможности сканировать истинный индекс с пропущенными повторами, т.е. искать верх, затем искать больше, чем верхний, а затем стремительно искать больше, чем считалось последним.
Есть ли способ использовать 'SKIP SCAN' в' SQL Server'? Я просто попробовал ваше решение на таблице «2M», и это стало еще хуже («DISTINCT CAST (...)» в поле «DATETIME» заняло «850 мс» с «Агрегатом совпадения хэшей», «ДАТА DISTINCT» «1800 мс» с «Сводным агрегатом»). «Oracle» и «MySQL» просто перепрыгивают через отдельные поля в индексе, «SQL Server» этого не делает. – Quassnoi
Вам нужно будет выбрать отдельную дату_значения после создания индекса на нем. –
'@ Remus': я создал индекс, и оптимизатор его использовал. – Quassnoi