使用检查点与 GO

Alf*_*f47 5 sql-server delete bulk checkpoint

通常,当开发人员或数据分析师之一需要执行非常大的数据更新或删除时(其中截断或截断/插入没有意义,因为要保留的数据集太大)我建议他们这样做类似于以下内容:

-- Delete 1 million rows 1 thousand at a time
DELETE TOP (1000) FROM TableA WHERE <condition>
WAITFOR DELAY '00:00:01'
GO 1000
Run Code Online (Sandbox Code Playgroud)

对处于完全恢复模式的数据库执行此操作的结果是 1) 等待允许其他事务在需要时进行处理 2) 当日志备份运行时,它能够在日志文件中将已完成的操作标记为脏操作可以复用空间,防止日志增长过快。

而不是这样做,我想知道是否可以使用检查点完成同样的事情。这句话是否会有效地导致同样的情况发生?

-- Delete 1 million rows 1 thousand at a time
WHILE EXISTS ( SELECT 1 FROM TableA WHERE <condition> )
BEGIN
DELETE TOP (1000) FROM TableA WHERE <condition>
WAITFOR DELAY '00:00:01'
CHECKPOINT
END
Run Code Online (Sandbox Code Playgroud)

同样,这些是处于完全恢复模式的数据库。

Kin*_*hah 2

进行大型更新或删除时最重要的是避免事务日志增长失控。允许日志重用并避免膨胀到 Tlog(事务日志截断

  • 在完全恢复模式下 - 进行日志备份
  • 在简单恢复模式下 - 执行检查点。

由于您使用的是完全恢复,因此您的删除逻辑应该是

begin
 begin tran
   -- delete using batches 
   -- carefully choose batch size. SQL Server will do a lock escalation 
   -- for batch greater than 5000. (https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx)
 commit tran / rollback tran 
  -- since you are using Full recovery, take log backups
  -- with CHECKPOINT SQL Server still cannot reuse those portions of the log until you perform a log backup.
end
Run Code Online (Sandbox Code Playgroud)

我习惯waitfor delay特别是。避免长时间阻塞。

请参阅 Aaron Bertrand 的这篇金矿博客文章 -将大型删除操作分解为块。另外,编写批处理脚本时要小心是非常有用的博客文章。