[SQL Server 2012]关于对海量数据进行批量更新的问题

时间:2021-10-21 13:25:50
请教大家一个SQL Server 2012对海量数据进行批量更新的问题:

我正在维护的系统中有一个表,有超过1000万条记录。最近进行了一项改造,需要每天从上游系统接收有更新的数据,约300万条记录,更新数据以文件的方式传送到本系统。本系统需要做的事情是将更新数据的所有字段更新(如果按主键在表中找到记录)或插入(如果按主键在表中未找到记录)表中。

目前的办法是:

1 创建一个结构与上面的表相同的表(以下称前者为A,后者为B)
2 使用bcp将更新数据导入到表B中
3 执行以下SQL删除表A中的数据:
  delete from 表A inner join 表B on 表A.主键字段 = 表B.主键字段
4 执行以下SQL将表B中的所有数据添加到表A中:
  insert into 表A select * from 表B

以上办法的效率很低,执行第3步都需要几个小时,必须进行优化。请问大家有什么好的建议?

5 个解决方案

#1


使用一个存储过程。

#2


循环写个删除脚本,每删除几千条commit一次。

#3


1000万、300万,不多,如果时效性要求不苛刻的话,循环删除,每次1000左右,但是不能超过5000(锁升级),如果时效性比较大,你可以考虑和测试一下这个方案:
1、创建同等结构的表(前提你的原表不能有过多的引用,比如有其他表、视图引用这个表)。
2、文件用bcp导入到一个临时表。
3、临时表与原表进行JOIN和where运算,得出需要更新的数据,插入到第一步中的新表。
4、把不需要修改的数据从原表移到新表。
5、删除原表,重命名新表。
6、对新表做维护工作。
7、做日志备份。

#4


对B表开游标,逐条循环:
1)A存在就更新(没必要先删再插)、不存在就插入;
2)删除B记录;
3)如果累计了1000条就递交一次事务。
分成小事务就快多了。
就算任务被中断,不用从头再来,最多就是最后被中断的一批要重做。

#5


为啥不用merge,你这本来是差异更新的,你却直接删除了。

#1


使用一个存储过程。

#2


循环写个删除脚本,每删除几千条commit一次。

#3


1000万、300万,不多,如果时效性要求不苛刻的话,循环删除,每次1000左右,但是不能超过5000(锁升级),如果时效性比较大,你可以考虑和测试一下这个方案:
1、创建同等结构的表(前提你的原表不能有过多的引用,比如有其他表、视图引用这个表)。
2、文件用bcp导入到一个临时表。
3、临时表与原表进行JOIN和where运算,得出需要更新的数据,插入到第一步中的新表。
4、把不需要修改的数据从原表移到新表。
5、删除原表,重命名新表。
6、对新表做维护工作。
7、做日志备份。

#4


对B表开游标,逐条循环:
1)A存在就更新(没必要先删再插)、不存在就插入;
2)删除B记录;
3)如果累计了1000条就递交一次事务。
分成小事务就快多了。
就算任务被中断,不用从头再来,最多就是最后被中断的一批要重做。

#5


为啥不用merge,你这本来是差异更新的,你却直接删除了。