玲液 发表于 2025-6-11 18:39:10

SQLServer中,大表的数据删除操作,单次删除和批量多次删除产生的事务日志的差别

 
1,应用场景

SQLServer中一个大表(测试环境千万级,实际情况下会更多,达到10亿级),删除其中大部分数据。然后测试分批多次删除和一次性全部删除产生的transaction log的日志大小的问题。另:受限于相关的表做了复制分发,因此无法通过备份部分数据后truncate table的方式来实现,也无法通过新建一个表,通过rename的方式来交换实现,这两种方式不再考虑范围之内,也不是本文的重点。  以下为生成测试数据库前置条件:1,数据库为SQLServer 2019标准版2,测试文件所在的磁盘为普通普通SSD(非NVME类型SSD)3,创建两个一样的数据库,保持数据库的初始大小,增长大小一致;日志的初始大小,增长大小一致,两个数据库均为full recovery模式4,两个库中定义完全一样的表,写入完全一致的测试数据,最低1000W起步,否则测试意义不大 以下为测试脚本USE
GO
CREATE DATABASE ON PRIMARY
( NAME = N'TransactionTest_01_Data', FILENAME = N'D:\MSSQL\Data\TransactionTest_01.mdf' , SIZE = 32768KB , MAXSIZE = UNLIMITED, FILEGROWTH = 32768KB)
LOG ON
( NAME = N'TransactionTest_01_Log', FILENAME = N'D:\MSSQL\Log\TransactionTest_01_Log.ldf' , SIZE = 65536KB , MAXSIZE = UNLIMITED, FILEGROWTH = 131072KB )
GO

USE
GO

CREATE DATABASE ON PRIMARY
( NAME = N'TransactionTest_02_Data', FILENAME = N'D:\MSSQL\Data\TransactionTest_02.mdf' , SIZE = 32768KB , MAXSIZE = UNLIMITED, FILEGROWTH = 32768KB)
LOG ON
( NAME = N'TransactionTest_02_Log', FILENAME = N'D:\MSSQL\Log\TransactionTest_02_Log.ldf' , SIZE = 65536KB , MAXSIZE = UNLIMITED, FILEGROWTH = 131072KB )
GO

use
go

create table test01
(
    c1 int identity(1,1),
    c2 varchar(100),
    c3 varchar(100),
    c4 varchar(100),
    c5 varchar(100),
    c6 varchar(100),
    c7 varchar(100),
    c8 varchar(100),
    c9 varchar(100),
    c10 datetime2,
    constraint pk_test01 primary key(c1)
);

use
go

create table test01
(
    c1 int identity(1,1),
    c2 varchar(100),
    c3 varchar(100),
    c4 varchar(100),
    c5 varchar(100),
    c6 varchar(100),
    c7 varchar(100),
    c8 varchar(100),
    c9 varchar(100),
    c10 datetime2,
    constraint pk_test01 primary key(c1)
);
go



--生成测试数据,这里是5千万,如果磁盘太慢或者其他原因,可以减小@i参数的值,少生成一些数据
declare @i int = 0
begin tran;
while @i<50000000
begin
    declare @var varchar(100) = newid();
    declare @currentdatetime datetime2 = sysdatetime();

    insert into TransactionTest_01..test01 values (@var,@var,@var,@var,@var,@var,@var,@var,@currentdatetime);
    insert into TransactionTest_02..test01 values (@var,@var,@var,@var,@var,@var,@var,@var,@currentdatetime);
   
    set @i = @i + 1;

    if @i%10000=0
    begin
      commit;
      begin tran;
    end
end

if @@trancount > 0
    commit;
go


--验证数据的一致性
select count(1) from TransactionTest_01..test01 with(nolock);
select count(1) from TransactionTest_02..test01 with(nolock);

select top 100 * from TransactionTest_01..test01 with(nolock) order by c1 desc;
select top 100 * from TransactionTest_02..test01 with(nolock) order by c1 desc;


场景1:
--批量删除,执行前重启SQLServer服务
while 1>0
begin
    delete top (5000) from TransactionTest_01..test01 where c1 < 15740000
    if @@rowcount=0
    begin
      break
    end
end


场景2:
--全量删除,执行前重启SQLServer服务
delete from TransactionTest_02..test01 where c1 < 15740000以下为生成的测试数据(受时间限制,仅生成了16百万的数据):
 
2,测试数据

两个库中,生成测试数据后,测试表的数据库完全一致


 
3,测试数据库的文件大小

两个库中,生成测试数据之后,测试数据的数据文件和日志文件完全一致。


 
4,删除数据后的事务日志大小(删除前后均不做事务日志备份)

4.1,批量删除测试库1中的数据,事务日志增加了400MB左右

4.2,整体删数测试库2中的数据,事务日志增加了31G左右

 
5,结论

对于完全一样的表,通过分批多次删除,和一次性删除,删除同样多的数据的情况下:
1,事务日志增长量400MB VS 31000MB,
2,执行耗时,115秒 VS 265秒

 
6,相关参考

这里有一篇相关性的文章,已经有十几年了,Break large delete operations into chunks(https://sqlperformance.com/2013/03/io-subsystem/chunk-deletes),也提到单次删除和分批删出的差异性,这篇文测试了很多的场景。
下面这个场景跟本文的场景类似:full recovery模式,单次删除和分批多次删除的对比,

文章的评论区有人问道:why 'chunks delete' generate less logging但回答是说批量删除备份日志,然后日志重用,这个回答并没有解释,在如上图的测试结果中,为什么没有日志备份的情况下,批量删除的日志量远小于单次删除
最终也没有解释出来根本原因:完整恢复模式下,不做日志备份,删除同样多的数据,单次删除和批量多次删除事务日志差异性的原因。
希望有看到的大佬指点一二

 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

郦珠雨 发表于 2025-10-13 00:43:36

新版吗?好像是停更了吧。

钦娅芬 发表于 2025-12-21 08:28:01

热心回复!

舒菀菀 发表于 2025-12-22 07:29:10

新版吗?好像是停更了吧。

诞楮 发表于 2026-1-6 11:03:37

前排留名,哈哈哈

致掣 发表于 2026-1-14 13:44:44

谢谢分享,试用一下

咳镘袁 发表于 2026-1-14 16:04:51

很好很强大我过来先占个楼 待编辑

氛疵 发表于 2026-1-17 22:11:38

懂技术并乐意极积无私分享的人越来越少。珍惜

艾晓梅 发表于 2026-1-21 02:15:45

过来提前占个楼

申倩语 发表于 2026-1-21 17:08:18

谢谢分享,试用一下

陈兰芳 发表于 2026-1-21 19:49:48

新版吗?好像是停更了吧。

账暴 发表于 2026-1-24 04:56:02

热心回复!

庇床铍 发表于 2026-1-30 02:24:15

谢谢分享,辛苦了

撙仿 发表于 2026-2-2 07:08:15

yyds。多谢分享

甘子萱 发表于 2026-2-6 06:07:23

感谢分享,学习下。

啤愿 发表于 2026-2-8 12:00:21

前排留名,哈哈哈

鞍汉 发表于 2026-2-10 13:23:34

鼓励转贴优秀软件安全工具和文档!

公新蕾 发表于 2026-2-10 14:29:35

感谢发布原创作品,程序园因你更精彩

廖彗云 发表于 2026-2-11 02:18:52

很好很强大我过来先占个楼 待编辑

聊账 发表于 2026-2-12 07:13:33

谢谢分享,试用一下
页: [1] 2
查看完整版本: SQLServer中,大表的数据删除操作,单次删除和批量多次删除产生的事务日志的差别