SQL索引 - 计算列与计算列使用的字段

时间:2009-12-16 20:59:19

标签: sql sql-server performance indexing

DBA的快速提问:

假设我的桌子上有2列,IsDeleted(位)和DeletedDate(datetime)。该表包含大约10,000,000行。

IsDeleted是一个计算列,用于检查DeletedDate是否为NULL;如果不是则返回1,如果是则返回0.

查询此表将主要在IsDeleted列上完成。

有人可以给我一些关于我应该在哪里申请索引的建议吗?

将它应用于IsDeleted字段会因SET QUOTED IDENTIFIER关闭而导致一系列问题,这不一定是交易破坏者,但会导致一些额外的工作。

即使我没有直接查询该字段,我是否会将任何好处应用于DeletedDate?我应该咬紧牙关并将其添加到IsDeleted吗?这两者之间的性能差异可以忽略不计吗?

再次感谢;如果你想要任何澄清;给我留言,我会更新我的帖子。

5 个答案:

答案 0 :(得分:3)

将索引放在位列上是没有意义的,因为它没有足够的选择性。执行查询时,SQL Server确定要使用的最合适的索引。如果您的索引不够有选择性,它将被忽略,或者它可能决定进行索引扫描而不是索引搜索。无论哪种方式,它都不会真正帮助那么多。

将索引放在DeletedDate上可能对某些查询有所帮助,但是由于选择性的原因,对NULL和“任何值”的过滤可能不会那么有用。

我鼓励你读这个: Seek Vs. Scan

答案 1 :(得分:1)

在值限制为非常小的域的属性上放置索引(显然两值是可能的最小值)除了特殊的边缘情况之外没有意义(例如当行分布为90%-10时)两个值之间的百分比)

这是因为使用索引来查找其中一个值(假设行均匀分布大约50-50)将返回表中总行数的大约一半。如果您创建的平衡树(B-Tree)索引是三层或四层深度,则表示每行检索3或4个IO操作,这将超过表中的行数。

答案 2 :(得分:1)

如果计算基于当前日期时间,则无法在IsDeleted 上放置索引,因为计算列的结果是非确定性的。这是基于时间的,并且可能在每次调用时都有不同的结果。有关详细信息,请参阅此msdn article

  

例如,如果表具有整数   列a和b,计算列   a + b可以被索引,但是被计算   列a + DATEPART(dd,GETDATE())   因为值无法索引   可能会在后续调用中发生变化。

如果日期比较变得过于昂贵,您必须安排更新语句以每隔'x'时间运行一次,为'过期'日期设置IsDeleted值:

UPDATE MyTable SET IsDeleted=1 WHERE IsDeleted=0 AND DeletedDate < getutcdate()

编辑:我最初误读了这个问题,当计算为NULL与非NULL时,它将是确定性的。使用确定性结果,PERSISTED关键字可用于存储空检查的结果:

IsDeleted AS DeletedDate IS NOT NULL PERSISTED

这可以避免一直运行datetime null检查。它将结果存储在表中,直到您更新DeletedDate列。你需要测试一下,这实际上是值得的,但我不认为DeletedDate NULL检查会非常昂贵。

索引任一属性可能没有多大意义,因为你基本上想要分开2组:删除和未删除。

答案 3 :(得分:1)

说分发是: 98%IsDeleted = 0 2%IsDeleted = 1

SQL Server是否足够聪明,只能在索引中存储IsDeleted记录的信息?

答案 4 :(得分:0)

我不认为你会看到将它添加到DeletedDate有什么好处。但是,如果你不确定,那么两种方式测试性能都应该很容易。