SQL Server批量更新锁定

时间:2012-05-10 05:17:00

标签: sql-server locking

考虑这个陈述:

update TABLE1 
set FormatCode = case T.FormatCode when null then TABLE1.FormatCode else T.FormatCode end,
    CountryCode = case T.CountryCode when null then TABLE1.CountryCode else T.CountryCode end 
    <SNIP ... LOTS of similar fields being updated> 
FROM TABLE2 AS T 
WHERE TABLE1.KEYFIELD = T.KEYFIELD

TABLE1被其他应用程序使用,因此锁定它应该是最小的 其他人不使用TABLE2,所以我不关心它。

TABLE1TABLE2各包含600K行。

上述语句会导致TABLE1上的表格锁定吗?

如何修改它以使其锁定最小?

也许使用游标逐个读取TABLE2行,然后为每一行更新TABLE1的相应行?

2 个答案:

答案 0 :(得分:1)

Sql将首先使用行锁。如果索引页中有足够的行被锁定,SQL将发出页锁。如果锁定了足够的页面,SQL将发出表锁。

所以它实际上取决于发出了多少锁。您可以在更新语句中使用锁定提示ROWLOCK。缺点是你可能有数千个行锁,而不是数百个页锁或一个表锁。锁使用资源,所以当ROWLOCK提示可能不会发出表锁时,它甚至可能更糟,因为它可能会使服务器资源匮乏并且在任何情况下都会降低它的速度。

您可以一次批量更新1000。游标真的会更新闻。实验监控器分析结果并根据您收集的数据做出选择。

答案 1 :(得分:0)

由于marc_s建议引入一个限制性更强的WHERE子句来减少行数,这应该有所帮助。

由于您的更新每晚发生,因此您似乎只希望更新自上次更新发生以来已更新的记录(即一天的更新日期)。但是,如果记录的一部分已经改变而不是全部改变,这只会使你受益。

我可能会尝试选择已更改为临时表的行的Id,然后作为更新的一部分加入临时表。要确定Id的列表,可以考虑如何执行此操作,例如在TABLE2上使用last changed列(如果TABLE2有一个);或者你可以比较TABLE1和TABLE2之间的每个字段,看看它们是否不同(注意空值),虽然这将包含很多额外的sql,可能还有一个维护难题。我能想到的第三个选项是对TABLE2有一个UPDATE触发器,当它们在白天更新到临时表时插入行的KEYFIELD,可以在每晚更新后清除临时表。