更新大表并最大限度地减少用户影响

时间:2012-10-25 00:48:09

标签: sql sql-server database

我对一般数据库/ sql服务器设计有疑问:

有一个包含300万行的表,可以24x7全天候访问。我需要更新表中的所有记录。你能给我一些方法来做到这一点,以便在我更新桌面时最大限度地减少用户影响吗?

提前致谢。

4 个答案:

答案 0 :(得分:4)

通常,您会编写一个更新语句来更新行。但在你的情况下,你真的想要分解它。

http://www.sqlfiddle.com/#!3/c9c75/6 是一个常见模式的工作示例。您不希望批量大小为2,可能需要100,000或25,000 - 您必须在系统上进行测试,以确定快速完成和低阻塞之间的最佳平衡。

declare @min int, @max int

select @min = min(user_id), @max = max(user_id)
from users

declare @tmp int
set @tmp = @min

declare @batchSize int
set @batchSize = 2


while @tmp <= @max
begin
  print 'from ' + Cast(@tmp as varchar(10)) + ' to ' + cast(@tmp + @batchSize as varchar(10)) + ' starting (' + CONVERT(nvarchar(30), GETDATE(), 120) + ')'
  update users
  set name = name + '_foo'
  where user_id >= @tmp and user_id < @tmp + @batchsize and user_id <= @max

  set @tmp = @tmp + @batchSize
  print 'Done  (' + CONVERT(nvarchar(30), GETDATE(), 120) + ')'

  WAITFOR DELAY '000:00:001'

end
update users
set name = name + '_foo' 
where user_id > @max

我们使用这样的模式来更新用户表大约10倍的表大小。拥有100,000块大概需要一个小时。当然,性能取决于您的硬件。

答案 1 :(得分:0)

为了最大限度地影响用户,我一次只更新一定数量的记录。在我看来,要更新的数量更多地取决于您的硬件。

答案 2 :(得分:0)

与所有数据库一样,它取决于。什么是负载模式(即,用户主要从表的末尾读取)?如果有的话,如何添加新记录?您的索引填充因子设置和实际值是多少?您的更新是否会强制重新计算任何索引?你能拆分更新以减少锁定吗?如果是这样,在发生故障时您是否需要强大的回滚功能?您是在每一行中设置相同的值,还是每行计算一次,或者您是否有每行来源匹配?

答案 3 :(得分:-1)

使用循环甚至光标一次一行地查看表格。确保每个更新都使用行锁。

如果您没有办法识别仍需要更新的行,请首先创建另一个表以保存主键和更新指示符,复制其中的所有主键值,然后跟踪您的距离在那张桌子上。

这也是最慢的方法。如果你需要它更快一点,一次更新几千行,仍然使用行锁提示。