【问题标题】:Updating 33 Million Rows - Optimization更新 3300 万行 - 优化
【发布时间】:2020-09-01 03:37:40
【问题描述】:

我正在更新一个有 3300 万行的表中的 varchar 列。这就是我想出的,脚本在我的开发机器上大约需要 50 分钟。有什么办法可以提高性能?

SET XACT_ABORT ON

DECLARE @NewPrefix VARCHAR(255)
        ,@OldPrefix VARCHAR(255)
        ,@Rowcount BIGINT = 1
        ,@BatchSize INT = 100000
        ,@ModBy VARCHAR(50)
        ,@ModStation VARCHAR(50)
        ,@UpdatedCount BIGINT = 0;

SET @ModBy = 'User1'
SET @ModStation = 'abc001'

SET @OldPrefix = 'http://OldPrefix/'
SET @NewPrefix = 'http://NewPrefix/'

WHILE (@Rowcount > 0)
BEGIN
    BEGIN TRANSACTION

    UPDATE TOP (@BatchSize) tblFiles
    SET FileLocation = REPLACE(FileLocation, @OldPrefix, @NewPrefix),
        ModDate = GETDATE(), 
        ModBy = @ModBy,
        ModStation = @ModStation
    WHERE ModStation <> @ModStation
      AND FileLocation IS NOT NULL

    SET @Rowcount = @@ROWCOUNT;
    SET @UpdatedCount = @UpdatedCount + @Rowcount

    COMMIT TRANSACTION
END

SELECT @UpdatedCount AS 'Records Updated.'

谢谢!

【问题讨论】:

  • 您的表中有(ModStation)(或(ModStation, FileLocation))的索引吗?这至少会加速要更新的行的“发现”
  • 匹配WHERE ModStation &lt;&gt; @ModStation AND FileLocation IS NOT NULL 的行中有多少包含您要替换的前缀?他们都是?如果不是什么比例?
  • 2600万符合条件FileLocation IS NOT NULL
  • @marc_s - 不,我在这些表上没有任何索引。

标签: sql-server sql-server-2017


【解决方案1】:

@ModStation 是一个常量时,我​​建议使用过滤索引,而不是为ModStation &lt;&gt; @ModStation 使用变量,而是ModStation &lt;&gt; 'abc001'

在脚本的开头:

CREATE INDEX IX_tblFiles_Temp
ON tblFiles
(
    YourPrimaryKey
)
WHERE ModStation <> 'abc001'
      AND FileLocation IS NOT NULL

并在脚本末尾删除索引。

如果 mod station 是一个变量,您仍然可以为文件位置创建过滤索引。

CREATE INDEX IX_tblFiles_Temp
ON tblFiles
(
    ModStation 
)
WHERE FileLocation IS NOT NULL

如果您要更新外键列,您可以选择在脚本开头删除/禁用外键约束,并在脚本末尾重新创建/启用它们。


还可以考虑在使用索引或增加批量大小时删除while(1.000.000 可能更快,具体取决于硬件、列的大小)


您还可以在更新中指定WITH (TABLOCK) 以锁定整个表。 (而不是锁升级) 示例

UPDATE TOP (@BatchSize) tblFiles
WITH (TABLOCK) -- Forcing a table lock
SET FileLocation = REPLACE(FileLocation, @OldPrefix, @NewPrefix),
    ModDate = GETDATE(), 
    ModBy = @ModBy,
    ModStation = @ModStation
WHERE ModStation <> @ModStation
      AND FileLocation IS NOT NULL

【讨论】:

    【解决方案2】:

    任何查询写入数据的性能损失的第一点是写入事务日志的速度。 确保事务日志的尺寸已经很好,就像每个 DBA 都应该为事务日志规划文件的容量一样。 事务日志的任何增长操作都会消耗时间……

    【讨论】:

      【解决方案3】:

      是的,可以提高您的计算机性能,例如内存和处理器

      【讨论】:

        猜你喜欢
        • 2014-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-14
        • 1970-01-01
        • 2019-11-23
        • 1970-01-01
        相关资源
        最近更新 更多