我对一般数据库/sql 服务器设计有疑问:
有一个包含 300 万行的表正在 24x7 访问。我需要更新表中的所有记录。你能给我一些方法来做到这一点,以便在我更新表格时将用户影响降至最低吗?
提前致谢。
我对一般数据库/sql 服务器设计有疑问:
有一个包含 300 万行的表正在 24x7 访问。我需要更新表中的所有记录。你能给我一些方法来做到这一点,以便在我更新表格时将用户影响降至最低吗?
提前致谢。
通常你会编写一个更新语句来更新行。但是在您的情况下,您实际上想将其分解。
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 个块大约需要一个小时。性能当然取决于您的硬件。
与所有事物数据库一样,这取决于。什么是负载模式(即用户主要从表格末尾阅读)?如果有的话,如何添加新记录?您的索引填充因子设置和实际值是多少?您的更新会强制重新计算任何索引吗?您可以拆分更新以减少锁定吗?如果是这样,您是否需要强大的回滚能力以防发生故障?您是在每一行中设置相同的值,还是需要每行计算,或者您是否有每行源来匹配?
为了尽量减少对用户的影响,我一次只更新一定数量的记录。在我看来,要更新的数量更多地取决于您的硬件。
使用循环甚至游标一次遍历表格一行。确保每次更新都使用行锁。
如果您无法识别仍需更新的行,请先创建另一个表来保存主键和更新指示符,将所有主键值复制其中,然后跟踪您的进度那张桌子。
这也将是最慢的方法。如果您需要它更快一点,一次更新几千行,仍然使用行锁提示。