0

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

有一个包含 300 万行的表正在 24x7 访问。我需要更新表中的所有记录。你能给我一些方法来做到这一点,以便在我更新表格时将用户影响降至最低吗?

提前致谢。

4

4 回答 4

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 个块大约需要一个小时。性能当然取决于您的硬件。

于 2012-10-25T01:04:21.340 回答
0

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

于 2012-10-25T01:02:29.677 回答
0

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

于 2012-10-25T00:58:41.640 回答
-1

使用循环甚至游标一次遍历表格一行。确保每次更新都使用行锁。

如果您无法识别仍需更新的行,请先创建另一个表来保存主键和更新指示符,将所有主键值复制其中,然后跟踪您的进度那张桌子。

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

于 2012-10-25T01:01:47.663 回答