【问题标题】:What is the best type of index for non-selective column?非选择性列的最佳索引类型是什么?
【发布时间】:2017-03-15 17:15:34
【问题描述】:

假设我有一张桌子:

create table MyTable
(
  column1 varchar(150),
  column2 ...,
  column3 ...,
  ...
)

Column1 包含 40% 的空记录,10% 的空 ('') 值,其余是一些有意义的值。 我有一些只适用于非空记录的查询:

select ...
from MyTable
join TableA ...
join TableB ...
...
where column1 is not null and column1 <> ''

但是没有查询可以通过 column1 的有意义值过滤数据集:

select column2
from MyTable
where column1 = 'abcde'  -- NOT COMMON

通过在 column1 上引入索引来将考虑的行数减半似乎是个好主意。我尝试使用简单的非聚集索引和过滤索引:

CREATE NONCLUSTERED INDEX IX_MyTable_column1
    ON dbo.MyTable(column1)
    WHERE column1 is not null and column1 <> ''

但优化器不想使用它,我在执行时间上没有任何好处。

我可以加快此类查询吗?最合适的索引类型是什么?

更新:

实际上索引用于只有表和精确索引谓词的简单查询,但如果我添加额外的谓词,例如column2 in (4, 7, 9) 它执行聚集索引扫描。复杂的多连接查询也是如此。

【问题讨论】:

  • 确保查询中的WHERE 过滤器与索引中的WHERE 过滤器紧密匹配。优化器应该能够使用这样的索引。另请参阅sqlblog.com/blogs/rob_farley/archive/2015/02/22/… 实质上,尝试将OPTION (RECOMPILE) 添加到查询中。
  • 是的,谓词完全匹配,唯一的区别是column1之前的别名。
  • 无索引 - 因为 50% 的记录满足您的条件。这就是优化器忽略这个索引的原因——它对任何事情都没有帮助。而且,正如您所展示的,您在 select 中引用了该表的其他列,因此该索引不是 覆盖 的。
  • 另外,看看sqlperformance.com/2013/04/t-sql-queries/…stackoverflow.com/questions/10897198/… 在非平凡的查询中,说服优化器生成最佳计划可能很棘手。我将从最简单的查询开始,检查它是否按预期使用索引,然后向它添加更多连接并观察计划在哪个点发生变化。

标签: sql-server performance sql-server-2008 indexing


【解决方案1】:

正如您所说,MyTable 的 column1 有一半的值不是 NULL 并且不是空字符串。因此,如果您使用过滤器 WHERE column1 is not null and column1 &lt;&gt; '' 在 column1 上创建索引,并且执行计划确实使用该索引,则应使用索引查找。

如果没有使用索引种子,那么我们需要检查估计行和实际行,如果它们相差很多行,则需要更新统计信息。

对于您的第一个查询: 选择 ... 从我的表 加入表A ... 加入表B ... ... 其中 column1 不为 null 且 column1 ''

大多数情况下执行计划会使用索引扫描。

【讨论】:

    【解决方案2】:

    这取决于索引的选择性。

    Do indexes work in NOT IN or <> clause?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    相关资源
    最近更新 更多