问答/ 问答详情 /

表空间自增异常

2025/03/20 274 14 已解决

为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】: image.png--03134283890-20220720-165295-10045 Pack11
【操作系统】:CentOS Linux 7
【CPU】:8C 16G
【问题描述】*:字符集 UTF-8,页大小32K
表空间自增异常,创建表空间默认扩展大小时是4M,但是使用过程中表空间增长异常大,期间没有大量删除操作,导致空间使用率极低,占用大量磁盘空间
试过逻辑备份还原和DTS迁移,导入新表空间也有同样的问题。

image.png
image.png

回答 14
六问

表空间创建的时候,初始化大小设置的是多少?

发布于 2025/03/20 09:44
回复 六问 :  

初始128M

发布于 2025/03/21 10:29
宁静致远

逻辑还原和DTS这种,涉及到了表数据的增长,这些表里边是否有大字段

发布于 2025/03/20 10:33
回复 宁静致远 :  

有大字段,初始化表空间才128M

发布于 2025/03/21 10:31
Hanson.T

下面内容只是我个人的理解,不知道是否属实,你可以测试验证下。

查一下下面这个SQL,看看目前在 129 这个表空间里有多少个索引。

SELECT COUNT(1),SF_GET_EXTENT_SIZE,PAGE FROM SYSINDEXES WHERE GROUPID = 129

复制

达梦在创建一张表或一个索引时,会初始分配至少1个簇的空间,比如1个簇是16页,每页32K,这样等于初始一张表或创建一个索引就会至少占用16*32=512K的大小。

现在你设置的数据文件每次扩展4M,也就是4096K,折算下来只相当于8个簇的大小。

如果创建了比较多的表或索引,那初始占用的空间就已经很大了。

当某个表中的数据占满了之前分配的簇空间后,再分配空间也是1个簇,也就是又分配16个32K页。

发布于 2025/03/20 11:21
回复 Hanson.T :  

image.png
算下来占用和空闲空间差的还是很大

发布于 2025/03/21 10:49
Hanson.T 回复 :  

1簇32页,1页32K,也就是说,1个簇会占用32*32=1024K,也就是1M。

现在索引(含聚簇索引)总数是3521,也就是创建了这些对象最小也要占用3521M.

从前面你查的V$DATAFILE信息看,目前该数据文件大小(TOTAL_SIZE)是186880页,算下来是5840M.

你可以用下面这个SQL查一下每个表的大小,看下是哪些表占用了较多的空间(每个值都拆成字节大小和页数)。

SELECT USR.NAME AS USER_NAME ,SCH.NAME AS SCHEMA_NAME ,TAB.NAME AS TABLE_NAME ,IDX.TSID ,IDX.TSNAME AS TABLESPACE_NAME ,ROUND(TABLE_USED_PAGES(SCH.NAME,TAB.NAME) * PAGE ,2) AS TABLE_SIZE_BYTES ,TABLE_USED_PAGES(SCH.NAME,TAB.NAME) AS TABLE_SIZE_PAGES ,ROUND(TABLE_USED_SPACE(SCH.NAME,TAB.NAME) * PAGE ,2) AS TABLE_SPACE_BYTES ,TABLE_USED_SPACE(SCH.NAME,TAB.NAME) AS TABLE_SPACE_PAGES ,CASE WHEN HAS_CLUSTER = 1 THEN ROUND(TABLE_USED_LOB_PAGES(SCH.NAME,TAB.NAME) * PAGE ,2) END AS TABLE_LOB_SIZE_BYTES ,CASE WHEN HAS_CLUSTER = 1 THEN TABLE_USED_LOB_PAGES(SCH.NAME,TAB.NAME) END AS TABLE_LOB_SIZE_PAGES ,CASE WHEN HAS_CLUSTER = 1 THEN ROUND(TABLE_USED_LOB_SPACE(SCH.NAME,TAB.NAME) * PAGE ,2) END AS TABLE_LOB_SPACE_BYTES ,CASE WHEN HAS_CLUSTER = 1 THEN TABLE_USED_LOB_SPACE(SCH.NAME,TAB.NAME) END AS TABLE_LOB_SPACE_PAGES ,IDX.CLUSTER_SIZE_BYTES ,IDX.CLUSTER_SIZE_PAGES ,IDX.CLUSTER_SPACE_BYTES ,IDX.CLUSTER_SPACE_PAGES ,IDX.INDEX_SIZE_BYTES ,IDX.INDEX_SIZE_PAGES ,IDX.INDEX_SPACE_BYTES ,IDX.INDEX_SPACE_PAGES ,COMM.COMMENT$ FROM SYSOBJECTS TAB JOIN SYSOBJECTS SCH ON SCH.TYPE$ = 'SCH' AND SCH.ID = TAB.SCHID JOIN SYSOBJECTS USR ON USR.TYPE$ = 'UR' AND USR.ID = SCH.PID JOIN (SELECT IDX.PID AS TABLE_ID ,TS.ID AS TSID ,MAX(TS.NAME) AS TSNAME ,MAX(DECODE(BITAND(IDXINFO.XTYPE,0x01),0,1,0)) AS HAS_CLUSTER ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),0,ROUND(INDEX_USED_PAGES(IDX.ID) * PAGE ,2)),0)) AS CLUSTER_SIZE_BYTES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),0,INDEX_USED_PAGES(IDX.ID)),0)) AS CLUSTER_SIZE_PAGES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),0,ROUND(INDEX_USED_SPACE(IDX.ID) * PAGE ,2)),0)) AS CLUSTER_SPACE_BYTES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),0,INDEX_USED_SPACE(IDX.ID)),0)) AS CLUSTER_SPACE_PAGES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),1,ROUND(INDEX_USED_PAGES(IDX.ID) * PAGE ,2)),0)) AS INDEX_SIZE_BYTES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),1,INDEX_USED_PAGES(IDX.ID)),0)) AS INDEX_SIZE_PAGES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),1,ROUND(INDEX_USED_SPACE(IDX.ID) * PAGE ,2)),0)) AS INDEX_SPACE_BYTES ,SUM(NVL(DECODE(BITAND(IDXINFO.XTYPE,0x01),1,INDEX_USED_SPACE(IDX.ID)),0)) AS INDEX_SPACE_PAGES FROM SYSOBJECTS IDX JOIN SYSINDEXES IDXINFO ON IDXINFO.ID = IDX.ID JOIN V$TABLESPACE TS ON TS.ID = IDXINFO.GROUPID WHERE IDX.TYPE$ = 'TABOBJ' AND IDX.SUBTYPE$ = 'INDEX' GROUP BY IDX.PID,TS.ID ) IDX ON IDX.TABLE_ID = TAB.ID LEFT JOIN SYSTABLECOMMENTS COMM ON COMM.TABLE_TYPE = 'TABLE' AND COMM.SCHNAME = SCH.NAME AND COMM.TVNAME = TAB.NAME WHERE TAB.TYPE$ = 'SCHOBJ' AND TAB.SUBTYPE$ IN ('STAB','UTAB') AND IDX.TSID = 129 ORDER BY TABLE_SPACE_PAGES DESC

复制

发布于 2025/03/21 11:43
Hanson.T 回复 :  

你说的空闲空间是指 V$DATAFILE里的FREE_SIZE吧?

这个FREE_SIZE是指空闲页数量。

比如说,创建一张空表后会初始分配1个簇的空间,共32页。
而实际只使用了2页,剩余30页都是FREE状态。
但这30页的空间并不是真正可以释放掉的,因为在分配簇时已经确认了簇相关的页号范围。

发布于 2025/03/21 11:52
Hanson.T 回复 Hanson.T :  

目前 TOTAL_SIZE是 186880,FREE_SIZE 是169754,差值是 17126页,平均到每个索引上是约5页左右。

去掉每个对象都会有的1个控制页,也就是平均下来每个索引使用了4个页(全满或半满状态的)。

按32K每页,不考虑页头占用大小,把树内节点页也算作数据页,每页都按全满(FULL)状态来计算,
就是每张表数据占用144KB,我觉得这个大小还好吧。

发布于 2025/03/21 12:03
回复 Hanson.T :  

理解了,开始主要是对空闲空间疑惑,因为达梦是参考了Oracle的架构,oracle里空闲表空间是可以使用的。达梦对于表空间使用分配是不是有些不合理,初始化就需要3.5G,空闲页不能回收,也不能再分配使用,oracle中这些表初始化只需要200M。对于测试创建大量数据库磁盘使用不太友好

发布于 2025/03/21 18:02
Hanson.T 回复 :  

抱歉,我刚刚才想明白,我前面对 V$DATAFILE 中 TOTAL_SIZE 和 FREE_SIZE 的描述是错误的。

TOTAL_SIZE 应该是指对这个表空间的数据文件分配的磁盘占用空间大小,并不是我前面描述的页面占用空间。
FREE_SIZE 则应该是指这个数据文件内未被分配的空间大小。

这样的话就存在些解释不清楚的地方了
前面查询索引数是 3521,按每个索引只创建一个簇,那初始化后占用页面数是 3521 * 32 = 112672页,应该剩余未分配页面数最大是 186880 - 112672 = 74208页
而目前从 V$DATAFILE 查询数据看,FREE_SIZE 是 169754 页。

可能我的理解还是有问题,有点晕。。。

😫

发布于 2025/03/21 23:16
Hanson.T 回复 Hanson.T :  

你得空时可以做一个实验。

首先查询一下 V$DATAFILE 中 FREE_SIZE 值。
然后随便创建一张表,结构很简单就可以,比如说
CREATE TABLE T_PGTST(A INT);
然后再查一下V$DATAFILE 看 FREE_SIZE变化多少。

如果FREE_SIZE减少了32,那就说明每创建一个表或索引会初始化一个簇页空间,并从可用空间里扣减1个簇的页数。
如果改变值小于32,比如只变小了2,则说明在你使用的DM版本中,这里记录的FREE_SIZE只计算了实际占用的页数,而不是按簇分配页数计算的。

我刚刚在我手头两个不同版本的库(210820 和 250117)分别测试了一下,两个库的簇大小都是16页

在250117版本中,新增一张表后,FREE_SIZE减少16,也就是减小一个簇的页数
在210820版本中,新增一张表后,FREE_SIZE减少2,也就是只计算了1个内节点页和1个控制页,其他簇页没有计算。

我看你这里版本是220720,估计也是类似的情况。

现在的问题就是,对于早期版本,这些空闲状态簇页是否可以被其他索引重用或被收回?

如果不能收回,则说明虽然FREE_SIZE只扣减了2个已使用页,但实际表空间里还是已经预分配了1个簇的页数,只是未使用页是不可收回或重用状态。
这样的话,你新增对象后表空间大小增长速度比较快就能解释了。

发布于 2025/03/22 00:03
回复 Hanson.T :  

测试了两个版本20220720和20230417,测试结果和你的一致,说明早期版本和高版本free_size意义就不一样。空闲簇页都不能被回收利用,导致数据文件占磁盘空间过快

发布于 2025/03/24 17:43
Hanson.T 回复 :  

我觉得你目前的问题还是簇页数和页面大小太大了。

可以测试下,单独建一个新实例,设置一簇16页,每页8K或16K大小。
然后初始化表和索引对象。再看下数据文件大小增长情况。

发布于 2025/03/24 17:49

相似问题

更多
  • 使用视图SYS.V$LONG_EXEC_SQLS 查询慢sql时,拿到的sql信息是不完整的,中间使用...省略号替代了

    发布于 2025/04/15

  • 系统保留字

    发布于 2025/04/15

  • .net执行Insert报不完整的语法项

    发布于 2025/04/15

  • go-20240918这个驱动能用在20240527的版本上吗

    发布于 2025/04/15

  • .netCore3.1连接数据库报错

    发布于 2025/04/15

扫一扫
联系客服