我尝试将数百万条记录插入到包含20个以上索引的表中。
在上一次运行中,每100,000行需要超过4小时,查询在3½天后被取消...
您对如何提高速度有任何建议。
(我怀疑很多索引都是原因。如果您也这么认为,如何在操作之前自动删除索引,然后再次创建相同的索引?)
额外信息:
状态更新:
接受的答案帮助我加快了速度。
答案 0 :(得分:42)
您可以禁用和启用索引。请注意,禁用它们可能会产生不必要的副作用(例如,具有重复的主键或唯一索引等),只有在重新启用索引时才会发现这些副作用。
--Disable Index
ALTER INDEX [IXYourIndex] ON YourTable DISABLE
GO
--Enable Index
ALTER INDEX [IXYourIndex] ON YourTable REBUILD
GO
答案 1 :(得分:7)
这听起来像是一个数据仓库操作。 在插入之前删除索引并在之后重建它们是正常的。
重建索引时,首先构建聚簇索引,然后反过来删除它。他们应该都有100%的填充因子。
代码应该是这样的
if object_id('Index') is not null drop table IndexList
select name into Index from dbo.sysindexes where id = object_id('Fact')
if exists (select name from Index where name = 'id1') drop index Fact.id1
if exists (select name from Index where name = 'id2') drop index Fact.id2
if exists (select name from Index where name = 'id3') drop index Fact.id3
.
.
BIG INSERT
RECREATE THE INDEXES
答案 2 :(得分:4)
如另一个答案所述,禁用索引将是一个非常好的开始。
每100,000行4小时 [...] 插入数据包含在每100,000行的事务中。
你应该考虑减少数量,服务器必须在事务中保持大量状态(因此可以回滚),这(与索引一起)意味着添加数据非常困难。< / p>
为什么不将每个insert语句包装在自己的事务中?
另请查看您正在使用的SQL的性质,您是在每个语句(和网络往返)中添加一行,还是添加多行?
答案 3 :(得分:3)
在这些情况下,经常会建议禁用然后重新启用索引。我对这种方法有疑问,因为:
(1)应用程序的DB用户需要通常不应具有的模式更改权限。 (2)首先选择的插入方法和/或索引模式可能不是最优的,否则重建完整的索引树不应该比一些体面的批量插入更快(例如,客户端一次发出一个插入语句,导致成千上万的服务器往返;或者在聚簇索引上选择不当,导致常量的索引节点拆分。)
这就是我的建议看起来有点不同的原因:
您可以在this article中找到更详细的信息。