【问题标题】:Improve update performance when setting column to null将列设置为空时提高更新性能
【发布时间】:2011-12-06 17:29:03
【问题描述】:

这里有点长镜头,但我在下面有一个简单的查询:

begin transaction       

update s
set s.SomeField = null
from someTable s (NOLOCK)

rollback transaction

在靠近 SQL Server 框的地方运行大约 30 秒。有什么技巧可以用来提高速度。该表有 144,306 行。

谢谢。

【问题讨论】:

  • SomeField 是索引的一部分吗?如果不回滚会发生什么?回滚占用了大部分时间,还是归零?
  • 是的,它是索引的一部分。回滚增加了大约 10 秒的时间。还是 20 秒似乎太多了。
  • from someTable s (NOLOCK) 完全没有意义。它不会减少锁定量,只需使用update someTable set SomeField = null
  • 如果这是常规操作,您将不得不查看您的架构或付出代价。涉及的每个索引 + 表,并且可能索引也会阻塞..
  • @Tony - 仅当系统上没有用户时才会这样做。

标签: sql performance sql-server-2008


【解决方案1】:

像这样的大型 UPDATE 命令性能的最大组成部分将是您的数据库日志的速度。

为了获得最佳性能:

  1. 确保 DB 日志(LDF 文件)与 DB 数据(MDF 文件)位于不同的物理主轴上
  2. 避免对日志卷进行奇偶校验 RAID,例如 RAID-5; RAID-1 或​​ RAID-10 更好
  3. 确保数据库日志文件已预先生成,并且在磁盘上物理上是连续的
  4. 确保您的服务器有足够的 RAM - 理想情况下,至少足以容纳包含已修改行的所有数据库页面

为您的数据驱动器使用 SSD 也可能会有所帮助,因为该命令会创建大量脏缓冲区,这些缓冲区稍后会被惰性写入器刷新到磁盘;这可能会使数据库上的其他操作在发生时变慢。

【讨论】:

    【解决方案2】:

    如果没有限制,并且您确实需要将该列的所有值设置为 NULL,那么我将测试删除该列并重新添加它。

    不确定这是否会更快,但我会调查一下。

    【讨论】:

    • 好主意,我会研究一下。
    • 不行。该列被多个索引引用。不会为此删除索引并重新创建它们。那将需要更长的时间。
    【解决方案3】:

    【讨论】:

    • 重新启用意味着需要重建索引。
    • @MartinSmith 这绝对正确。但是,一次重建索引可能比将索引更新与表更新混合起来更便宜。我并不是说它一定会带来改进,但它有足够的成功机会尝试一下。
    • 禁用/重建几乎没有(几秒钟)提高了性能。
    【解决方案4】:

    您可以稍微更改查询的语法,但这样做对我的测试没有任何影响。我使用的是STATISTICS IOSTATISTICS TIME

    您提到该列已编入索引。作为交易的一部分,您可以禁用/重新启用它。 t-sql 很简单,看这个 - http://blog.sqlauthority.com/2007/05/17/sql-server-disable-index-enable-index-alter-index/

    我过去曾为类似的工作这样做过,这对我来说效果很好。

    【讨论】:

      【解决方案5】:

      尝试这样实现

      Disable Index
      
      Drop the column
      Create the column
      
      Rebuild index
      

      我猜它会提高性能。

      【讨论】:

      • 除了删除/创建列和索引的看似额外的开销之外,这与上述答案有何不同?
      猜你喜欢
      • 2011-10-14
      • 1970-01-01
      • 2013-12-08
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多