问题描述
我正在更新具有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都要通过计划事务日志文件的容量一样。 事务日志的任何增长操作都会消耗时间...
,是的,可以提高计算机的性能,例如内存和处理器