记一次SQL Server数据库表体积缩减操作
郝伟 2022/02/23
本文针对给定目标数据库的主要数据表进行删除,将数据库体重从原来的200GB+,缩小为10GB。
首先,在拿到这个数据库以后,希望对数据库的数据情况有初步了解。因此使用以下SQL语句查看数据库中各表的记录数最多的最20张表:
SELECT TOP(10) schema_name(systable.schema_id) as TableSchema, systable.name as TableName, sysids.rows as NumberOfRows FROM sys.tables as systable, sysindexes as sysids WHERE systable.object_id = sysids.id and sysids.indid <=1 and sysids.rows > 10 ORDER BY NumberOfRows DESC
返回结果如下
| TableSchema | TableName | NumberOfRows |
|---|---|---|
| dbo | RESULT | 50,525,591 |
| dbo | CURVE | 32,477,206 |
| dbo | RESULT_GUID | 4,613,348 |
| dbo | USER_INFO | 4,868 |
| dbo | TIGHTENING_UNIT_CHANGE | 3,235 |
| dbo | CONTROLLER_CHANGE | 2,357 |
| dbo | TOOL | 278 |
| dbo | USER_INFO_DEF | 225 |
| dbo | USER_INFO_TXT | 185 |
| dbo | STEP | 124 |
如表所示,数据量最大的是RESULT表和CURVE表,简单查看可以发现 RESULT.RES_ID 和 CURVE.CRV_ID为 为主键,同时在 CURVE 表关联了RESULT表,使用 CURVE.CRV_ResultID 与 RESULT.RES_ID 关联。 从业务层面看,RESULT 表中应该是结果,而有些结果会有曲线(CURVE)。 进一步验证,发现确实存在 RESULT.RES_ID 和 CURVE.CRV_ID 的约束。
既然这两个是主表,而且都有主键,数据都是增量添加,所以只需要根据主键删除即可。由于约束的存在,所以先删除 CURVE 中的数据再删除RESULT中的数据,具体执行结果如下:
DELETE CURVE WHERE CRV_ResultID <= 48500000
删除2000万条数据用时约4个小时。
DELETE RESULT WHERE RES_ID <= 48500000
执行用了约6个小时。
执行完以后,数据确实是变化了,可以使用 COUNT() 进行验证。但是查看数据库文件信息,发现执行后数据文件体积反而变大了:
cvinet.mdf 323 GB (347,240,136,704 字节)
cvinet_log.ldf 471 GB (506,274,971,648 字节)
其中,数据文件 cvinet.mdf 没有变化, 而日志文件 cvinet_log.ldf 由原来的几十GB增长到471GB,增加了约400GB。
在执行了 任务 -> 收缩 -> 文件 后,发现体积仍然是一样没有变化。
# 收缩文件后
-- cvinet.mdf 323 GB (347,240,136,704 字节)
-- cvinet_log.ldf 471 GB (506,274,971,648 字节)
再执行 任务 -> 收缩 -> 数据库 后,发现体积终于大幅缩小了。
# 收缩数据库后
-- cvinet.mdf 7.8 GB (8,019,334,592 字节)
-- cvinet_log.ldf 471 GB (506,274,971,648 字节)
首先,关闭所有连接和查询窗口。然后选择 任务 -> 分离,执行成功后即可删除 cvinet_log.ldf 文件。然后再选择附加数据库,将cvinet.mdf添加进来,即可完成整个数据库收缩工作。
删除后统计数据如下:
| TableSchema | TableName | NumberOfRows |
|---|---|---|
| dbo | RESULT_GUID | 4,613,348 |
| dbo | RESULT | 1,525,591 |
| dbo | CURVE | 477,206 |
| dbo | USER_INFO | 4,868 |
| dbo | TIGHTENING_UNIT_CHANGE | 3,235 |
| dbo | CONTROLLER_CHANGE | 2,357 |
| dbo | TOOL | 278 |
| dbo | USER_INFO_DEF | 225 |
| dbo | USER_INFO_TXT | 185 |
| dbo | STEP | 124 |
Select TOP 1 RES_DateTime from RESULT Order by RES_ID desc -- 2020-11-14 03:08:09.000 to 2021-08-27 09:25:53.000 Select TOP 10 RES_ID, RES_DateTime from RESULT Where RES_ID > 48500000 Order BY RES_ID SELECT COUNT(RES_ID) FROM RESULT WHERE RES_ID > 48500000 DELETE RESULT WHERE RES_ID <= 48500000 SELECT COUNT(RES_ID) FROM RESULT -- DELETE CURVE WHERE CRV_ResultID <= 48500000 -- 收缩文件没有用 -- 收缩数据库前 -- cvinet.mdf 323 GB (347,240,136,704 字节) -- cvinet_log.ldf 471 GB (506,274,971,648 字节) -- 收缩数据库后 -- cvinet.mdf 323 GB (347,240,136,704 字节) -- cvinet_log.ldf 471 GB (506,274,971,648 字节) SELECT TOP(10) schema_name(systable.schema_id) as TableSchema, systable.name as TableName, sysids.rows as NumberOfRows FROM sys.tables as systable, sysindexes as sysids WHERE systable.object_id = sysids.id and sysids.indid <=1 and sysids.rows > 10 ORDER BY NumberOfRows DESC