1,应用场景
SQLServer中一个大表(测试环境万万级,实际环境下会更多,达到10亿级),删除此中大部分数据。然后测试分批多次删除和一次性全部删除产生的transaction log的日记巨细的问题。另:受限于相干的表做了复制分发,因此无法通过备份部分数据后truncate table的方式来实现,也无法通过新建一个表,通过rename的方式来交换实现,这两种方式不再考虑范围之内,也不是本文的重点。 以下为天生测试数据库前置条件:1,数据库为SQLServer 2019标准版2,测试文件所在的磁盘为普通普通SSD(非NVME类型SSD)3,创建两个一样的数据库,保持数据库的初始巨细,增长巨细,日记的初始巨细,增长巨细,两个数据库均为full recovery模式4,两个库中界说完全一样的表,写入完全划一的测试数据,最低1000W起步,否则测试意义不大 以下为测试脚本- USE [master]
- GO
- CREATE DATABASE [TransactionTest_01] 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 [master]
- GO
- CREATE DATABASE [TransactionTest_02] 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 [TransactionTest_01]
- 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 [TransactionTest_02]
- 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秒
这里有一篇很早的文章Break large delete operations into chunks(https://sqlperformance.com/2013/03/io-subsystem/chunk-deletes),也提到单次删除和分批删出的差异性,这篇文测试了很多的场景。
下面这个场景跟本文的场景类似:full recovery模式,单次删除和分批多次删除的对比,
文章的品评区有人问道:why 'chunks delete' generate less logging但答复是说批量删除备份日记,然后日记重用,这个答复并没有表明,在如上图的测试结果中,为什么没有日记备份的环境下,批量删除的日记量远小于单次删除
最终也没有表明出来根本原因:完整恢复模式下,不做日记备份,删除同样多的数据,单次删除和批量多次删除事件日记差异性的原因。
渴望有看到的大佬辅导一二
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |