DBA的快速提问:
假设我的桌子上有2列,IsDeleted(位)和DeletedDate(datetime)。该表包含大约10,000,000行。
IsDeleted是一个计算列,用于检查DeletedDate是否为NULL;如果不是则返回1,如果是则返回0.
查询此表将主要在IsDeleted列上完成。
有人可以给我一些关于我应该在哪里申请索引的建议吗?
将它应用于IsDeleted字段会因SET QUOTED IDENTIFIER关闭而导致一系列问题,这不一定是交易破坏者,但会导致一些额外的工作。
即使我没有直接查询该字段,我是否会将任何好处应用于DeletedDate?我应该咬紧牙关并将其添加到IsDeleted吗?这两者之间的性能差异可以忽略不计吗?
再次感谢;如果你想要任何澄清;给我留言,我会更新我的帖子。
答案 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有什么好处。但是,如果你不确定,那么两种方式测试性能都应该很容易。