我可以通过在列x上创建索引来优化SELECT DISTINCT x FROM hugeTable查询吗?

pol*_*nts 22 sql t-sql indexing sql-server-2005 query-optimization

我有一个巨大的表,在某些列上具有更小的数量(按数量级)不同的值x.

我需要做一个查询SELECT DISTINCT x FROM hugeTable,我想要相对快速地做这个.

我做了类似的事情CREATE INDEX hugeTable_by_x ON hugeTable(x),但由于某种原因,即使输出很小,查询执行也不是那么快.查询计划显示97%的时间花在索引扫描上hugeTable_by_x,估计行数等于整个表的大小.接下来是哈希匹配操作.

由于我在列上创建了索引x,我不能指望此查询运行得非常快吗?

请注意,我正在使用Microsoft SQL Server 2005.

Rem*_*anu 22

这可能不是索引问题,而是数据设计问题之一.准确归一化.您需要查询字段的不同值,甚至愿意添加索引这一事实强烈表明该字段应该规范化为具有(小)连接键的单独表.然后,通过扫描小得多的查找外表,可以立即获得不同的值.

更新
作为一种变通方法,您可以通过"distinct"字段在聚合上创建索引视图.COUNT_BIG是索引视图中允许的聚合:

create view vwDistinct
with schemabinding
as select x, count_big(*)
from schema.hugetable
group by x;

create clustered index cdxDistinct on vwDistinct(x);

select x from vwDistinct with (noexpand);
Run Code Online (Sandbox Code Playgroud)

  • 虽然你所说的绝对正确,但你所说的情况可能正是为什么要执行“SELECT DISTINCT”,作为规范化过程的一部分。例如,我们有一个系统,它从一组下载的 FTP 文件中引入数据源。该数据根本没有标准化。我们流程的精确功能之一就是在将数据加载到系统中时对其进行标准化。例如,我们有一个查询(伪代码),例如“INSERT INTO NORMALIZEDVALUELIST (NAME) SELECT DISTINCT SOMEFIELD FROM UNNORMALIZEDSOURCE WHERE <SOMEFIELD NOT IN NORMALIZEDVALUELIST(NAME)>”。 (3认同)

Mar*_*ith 6

SQL Server没有实现任何工具来直接寻找索引中的下一个不同值,同时跳过重复项.

如果您有许多重复项,那么您可以使用递归CTE来模拟这一点.这个技术来自这里.("使用递归CTE的超快速DISTINCT").例如:

with recursivecte as (
  select min(t.x) as x
  from hugetable t
  union all
  select ranked.x
  from (
    select t.x,
           row_number() over (order by t.x) as rnk
    from hugetable t
    join recursivecte r
      on r.x < t.x
  ) ranked
  where ranked.rnk = 1
)
select *
from recursivecte
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)


Ode*_*ded -1

可能吧。尽管不能保证 - 这完全取决于查询。

我建议阅读 Gail Shaw 的这篇文章(第 1 部分第 2 部分)。