在datetime字段中涉及CAST或TRUNCATE或DATEPART操作的每个选项都具有相同的问题:查询必须扫描整个结果集(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不具备通过跳过重复扫描真正索引的功能,即,寻求最高,然后寻求超越最高,然后连续追求超过最后发现。
有没有办法使用'跳过'SQL Server' SCAN'?我只是想你的解决方案在'2M'表,并在'DATETIME'场了'用'哈希匹配Aggregate' 850个ms'得到更糟糕('DISTINCT CAST(...)','DISTINCT date'了带有“流聚合”的1800毫秒)。 'Oracle'和'MySQL'只会跳过索引中的不同字段,'SQL Server'不会这样做。 – Quassnoi 2009-08-20 17:25:13
您需要在创建索引后选择不同的date_only。 – 2009-08-20 17:59:34
'@ Remus':我确实创建了一个索引,并且优化器确实使用了它。 – Quassnoi 2009-08-20 18:09:36