达梦数据库-学习-21-某表的空间占用过大处理过程
目录
一、环境信息
二、介绍
三、优化过程
1、类型映射
2、表结构
3、计算
4、为什么不直接删除数据
5、重建表
四、分析总结
五、建议及改进
一、环境信息
名称 | 值 |
CPU | 12th Gen Intel(R) Core(TM) i7-12700H |
操作系统 | CentOS Linux release 7.9.2009 (Core) |
内存 | 4G |
逻辑核数 | 2 |
DM版本 | 1 DM Database Server 64 V8 2 DB Version: 0x7000c 3 03134284194-20240703-234060-20108 4 Msg Version: 12 5 Gsu level(5) cnt: 0 |
二、介绍
客户反馈达梦数据库某站业务表,空间占用了413G,需分析原因。
三、优化过程
LENGTHB函数计算文本大字段中存储的数据字节数,其中一个字段存的都是NULL,我们不计算在内,大字段占用5G左右,由于达梦是C语言实现的,我们以C语言数据类型来进行实际计算。
1、类型映射
数据类型 | C类型 | C类型字节数 |
BIGINT | long long | 8 |
VARCHAR | char | 1 * 字符个数 |
TEXT | unsigned char | 1 * 字符个数 |
BIT | char | 1 |
DATETIME | dpi_timestamp_t | 16 |
2、表结构
列号 | 类型 |
1 | VARCHAR(32) |
2 | VARCHAR(32) |
3 | BIGINT |
4 | DATETIME(6) |
5 | BIGINT |
6 | DATETIME(6) |
7 | BIT |
8 | VARCHAR(1) |
9 | DATETIME(6) |
10 | VARCHAR(64) |
11 | TEXT |
12 | BIGINT |
13 | BIGINT |
14 | VARCHAR(1) |
15 | TEXT |
3、计算
>>> (32 + 32 + 8 + 16 + 8 + 16 + 1 + 1 + 16 + 64 + 8 + 8 + 1) * 50000 / 1024 / 1024 / 1024 + 5
5.009825453162193
我们计算应该是5G左右,这里不涉及加密算法和压缩算法,但实际却占用413G,可以想到此表是由于频繁删除和更新此表导致的碎片化(空洞率过高)。
4、为什么不直接删除数据
数据库内部在删除数据时,只是给此数据打上删除标签,并没有真正的删除,这么做是为了提高并发效率,如果实时删除,我们就需要将树进行实时的旋转,来达到树的相对平衡,效率较低。
5、重建表
通过重建表,降低表碎片,具体步骤如下:
CREATE TABLE ZXJ.TEST_BAK_2025_03_05 AS SELECT * FROM ZXJ.TEST WHERE 1=2;
LOCK TABLE ZXJ.TEST IN EXCLUSIVE MODE;
INSERT INTO ZXJ.TEST_BAK_2025_03_05 SELECT * FROM ZXJ.TEST; -- 或者直接取影响行数,就不用统计ZXJ.TEST_BAK_2025_03_05条数。
-- SELECT count(*) FROM ZXJ.TEST_BAK_2025_03_05;
-- SELECT count(*) FROM ZXJ.TEST;
-- 对比数据是否相等
TRUNCATE TABLE ZXJ.TEST; -- 隐式提交释放锁
INSERT INTO ZXJ.TEST SELECT * FROM ZXJ.TEST_BAK_2025_03_05;
COMMIT; -- 释放锁
DROP TABLE ZXJ.TEST_BAK_2025_03_05;
重建后,通过视图查询,数据大小回缩到了5G。
SELECT T.SEGMENT_NAME, T.SEGMENT_TYPE, SUM(T.BYTES / 1024 / 1024 / 1024) AS "占用空间(G)"
FROM DBA_SEGMENTS T
WHERE T.SEGMENT_TYPE = 'TABLE'
AND
T.OWNER = 'SESP_PROD'
GROUP BY T.SEGMENT_NAME, T.SEGMENT_TYPE;
四、分析总结
本次表的空间占用过大的主要问题是:
生产环境对业务表频繁进行增删改,导致表碎片化严重,发生了数据量不大,但实际占用空间过大的问题。
五、建议及改进
建议按照上面提供的清理碎片化的方法,定时进行清理,避免影响数据库性能和磁盘空间的多余占用。