SQL Server 锁定的 UPDATE 优化
Posted
技术标签:
【中文标题】SQL Server 锁定的 UPDATE 优化【英文标题】:UPDATE optimization for SQL Server locking 【发布时间】:2021-05-10 13:47:42 【问题描述】:关于 SQL Server 如何锁定数据,与更新整行相比,更新表行中的单个列有什么好处?
据我了解,SQL Server 无法将数据锁定在比表格行更细的级别。例如,给定具有 A、B、C、D、E 列的行,其中 A 是主键,更新不能更改 B/C 列,而另一个更新会修改 D/E 列,对吗?
假设我对 SQL Server 锁定的假设是正确的,我是否可以推断更新一行中的单个列而不是更新整行不会带来性能优势?
进一步更详细地说明问题的示例场景:给定一个包含列的表(产品):uuid(主键)、长度、宽度、高度、重量
场景#1
ProductDAO.updateLength(Long uuid, float length);
ProductDAO.updateWidth(Long uuid, float weight)
场景#2
ProductDAO.update(Long uuid, float length, float width, float height, float weight)
主要问题: 在防止死锁和最大化 UPDATE 查询吞吐量的背景下,场景 #1 和 #2 是否实际上相同,或者是否有充分的理由创建更精细的更新函数?
显然,场景#2 的好处是测试/维护的代码要少得多,因为我们可以对大多数更新使用单个函数,这将允许我们将对象的存储库视为这些对象的内存集合.
【问题讨论】:
是的,行锁是最细粒度的锁。您的方案#2是首选,无论您是更新单列还是多列,它的“成本”都是相同的。 Sql server读取或写入的最小数据量是一个8k的数据页。 我认为这也取决于表的索引,假设您没有涉及列的索引或触发器,而不是 #2 应该是首选。 索引有利于定位要更新的行,我看不出它是否有任何相关性是否完成 1 或 2 行更新 - 除了两次更新需要第二次查找或重复扫描没有任何好处。 因为大多数时候答案是“视情况而定”。有很多因素会影响这一点。这取决于表上有哪些索引、是否正在更新聚集键以及许多其他因素。通常,假设您需要更新多个列,最好一次更新所有列。性能方面,最好在更新之前检查您是否实际更改了值。我见过很多 proc 无缘无故地更新行,这通常会对性能产生很高的影响。 @Stu 更新的列也会锁定相关索引。如果您不更新索引中的任何列,则该索引将根本不会被锁定 【参考方案1】:你的理解有不正确的词,揭示了一些误解......
与每个 RDBMS 一样,最小锁是一行。但是如果有很多索引包含相关列的更新值,所有的索引也会被锁定。 这是为了保证数据库及其访问的一致性。
使用多个 UPDATE 单独和迭代地更新同一记录的多个列,而不是在单个 UPDATE 中更新整个目标列,这将是最糟糕的,因为将为每个单个 UPDATE 建立和释放锁,导致:
1 - 一个耗时的问题
2 - 更新事务异常的可能松动
至少要说一下,当您执行许多更新时,其他一些用户也可以更新与您相同的行和同一列之一,因此您最终不会获得正确的值行!
【讨论】:
以上是关于SQL Server 锁定的 UPDATE 优化的主要内容,如果未能解决你的问题,请参考以下文章