在位列上添加索引会大大降低插入速度吗?


11

我有一张桌子,上面有大约100万到500万条记录。该记录的一小部分将bit列之一设置为“ TRUE”。需要快速找到该记录。我认为该索引可以加快在此列上的搜索,但是我担心INSERT。因此,我的问题。

数据库的工作就像某种数据仓库,因此有很多SELECT和小的选择(每天最多10到20个),但有很大的INSERT(一次最多有20万条记录)。我担心导入数据库的时间较长。


5
什么版本的SQL Server?如果2008+听起来像是经过筛选的索引,那么您将需要什么。
马丁·史密斯

SQL Server 2005
marioosh

1
您可以拆分表(添加仅包含一列的新表,即表的PK,其中仅填充那些位列为true的行-最后,您甚至可以删除该位列。)由于缺乏部分索引,这种观点在2005年同样适用。
ypercubeᵀᴹ

请注意索引视图,因为您提到每天有10-20个较大的插入,维护索引视图可能会超过性能提升的好处。我认为您无法利用SQL 2005的任何“即用型功能”来改善您的情况。但是如果您列出当前的表结构和现有索引,我们可能会找到一些替代设计。
Anup Shah 2014年

Answers:


8

一百万条记录的索引毫无用处。优化器永远不会使用它,您只需为维护它付费。更好的选择是将此位添加为聚簇索引的最左键。

但是我会在黑暗中瞎眼,然后猜测您所拥有的是队列模式:将记录放到表中,并将位设置为“ TRUE”(即“ needsprocessing = true”),然后查找后台进程对于这些记录,请进行一些处理,然后将该位更新为FALSE。这是一个无所不在的模式,也被亲切地称为“性能灾难配方模式”。我建议同时将记录放入表中,并将通知(可能与新插入的记录ID一样简单)同时放入队列中。请参阅将表用作队列


1
我看不到将bit列放在最左侧的任何好处,因为我们不知道其他具有高基数用户的过滤器列。到目前为止,我已经看到BIT列是聚簇索引中的最后选择。但是可以,+ 1是“将表用作队列”的不错参考。
Anup Shah 2014年

2
实际上,我运行了一个测试,是的,它将使用索引。创建一个表(Id标识,myBit位),然后添加100行(位为0)和2000000(位为1)。确保更新了统计信息(如果需要)并在myBit = 0上运行查询,将使用索引。
肯尼斯·费舍尔

@KennethFisher,不同之处在于,在典型的高速模式中,立即插入TRUE /更新为FALSE会使统计信息始终过时。如果您更喜欢使用优化程序玩俄罗斯轮盘赌而不是进行清晰的设计,那么您会得到应有的...
Remus Rusanu 2014年

该语句在“永远不会使用它”的情况下适用于99%的情况,但是我们不知道OP处于哪种情况。已经成功地对索引进行了索引。存在用例。
usr

问题- 这里的答案是错误的,特别是>“当您为一个位字段建立索引(或某个狭窄范围)时,仅将工作集减少与该值匹配的行数。如果与之匹配的行数少这将大大减少您的工作集。对于具有50/50分布的大量行,与保持索引为最新状态相比,它可能不会给您带来多少性能提升。” 在这种情况下,如果某个位的索引与记录的1%匹配,那么就无需扫描100万个记录中的99%来获得显着提升?
drzaus 2015年

2

正如@MartinSmith所说,如果您升级到SQL 2008,则过滤索引将是理想的解决方案。但是,在一般情况下,任何时候添加任何索引都会增加您的加载时间。小索引比大索引少。

我要看的一件事是,如果您有一个可以修改的现有索引。假设现有查询正在使用给定索引,则将bit列添加到该索引的末尾对插入的影响最小,而对查询的影响则很小。

接下来要看的是“我已经有很多索引了吗?” 关于“多少”没有硬性规定,但是除非我真的需要一个新的索引,否则通常以10个索引为限。

最后想到的是,在测试实例上进行测试。设置一个包含几百万行的表,对其进行加载,添加索引,然后再次运行加载,看看是否发现加载时间显着增加。

只有您才能真正决定“重要”是什么。我的机器在加载时间上增加了5分钟是“显着的”,而在其他机器上我可以安全地看到增加了几个小时。

编辑:

另一个选择是对表进行分区。如果您不使用企业版,则可能必须使用分区视图,即使这样也应有所帮助。您将0位放在一个分区中,将1位放在另一个分区中。假设您仅插入一个版本或另一个版本,那么您甚至可以加快插入速度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.