0

考虑这个陈述:

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

4

2 回答 2

1

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

所以这真的取决于发出了多少锁。您可以在更新语句中使用锁定提示 ROWLOCK。不利的一面是,您可能会拥有数千个行锁,而不是数百个页锁或一个表锁。锁使用资源,因此虽然 ROWLOCK 提示可能不会发出表锁,但它可能会更糟,因为它可能会使您的服务器资源匮乏并在任何情况下减慢它的速度。

您可以一次批量更新 1000 个。光标真的会更多地报道事情。实验监视器分析结果并根据您收集的数据做出选择。

于 2012-05-10T06:19:35.543 回答
0

正如marc_s所建议的那样,引入更具限制性的 WHERE 子句来减少行数应该会有所帮助。

由于您的更新每晚发生一次,因此您似乎只希望更新自上次更新以来已更新的记录(即一天的更新)。但这只会在部分记录发生变化而不是全部发生变化的情况下对您有利。

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

于 2012-05-10T06:30:13.560 回答