更新3,300万行-优化

问题描述

我正在更新具有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 <> @ModStation使用变量,而应该使用ModStation <> '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
,

在任何查询写入数据中,性能​​损失的第一点是写入事务日志的速度。 确保事务日志的大小合理,就像每个DBA都要通过计划事务日志文件的容量一样。 事务日志的任何增长操作都会消耗时间...

,

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