暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Oracle表空间碎片维护

IT那活儿 2024-09-01
279

点击上方“IT那活儿”公众号--专注于企业全栈运维技术分享,不管IT什么活儿,干就完了!!!   


表空间碎片说明

在Oracle数据库中,表空间碎片指的是表空间中存在未被充分利用的空间片段(extent)

这些空间片段可能是由于数据的增删改操作导致,造成表空间中存在一些零散的、不连续的数据块。表空间碎片可能会影响数据库性能和空间利用效率,也就是存在空闲空间,但是无法被使用,造成业务在对数据库表的增删改时提示空间不足的问题。


Oracle存储逻辑结构

Oracle存储的逻辑结构由表空间、段、区间、块组成,区间是数据库存储空间分配的逻辑单位,由一些连续数据块组成。一个或多个区间又构成了一个段。当现有分配的区间被完全使用的时候,Oracle就会为段分配一个新的区间。

对于AutoAllocate管理的区间而言,你可以指定初始段的大小,然后由Oracle决定新增区间的大小,最小区间大小为64k。自动扩展空间的选择有64K,1M,8M,64M。


表空间监控

为了防止表空间碎片过高导致表空间不可用问题,我们优化了表空间监控语句,增加了碎片空间监控,也就是不再只是仅仅监控剩余空间,而是将剩余空间减去碎片空间,得出的才是可用空间;
因为每个库大小不一,表的增删改每次获取的空间大小不一致,我们采用最大指标64M来进行监控,当获取不到64M的连续数据块时(extent),这些不连续的数据块被认定为碎片。
以下是最新表空间监控语句:

select  a.TABLESPACE_NAME "TBNAME",
    a.SPLINTER_SPACE "GetTableSplinterSize",
    a.SP_RATE "GetTableSPSizePused"
  from 
    (SELECT D.TABLESPACE_NAME,
        TO_CHAR(SPACE,'fm999990.99') SPACE,
        BLOCKS SUM_BLOCKS,
        TO_CHAR(SPACE - NVL(FREE_SPACE, 0),'FM999990.00') "USED_SPACE",
        TO_CHAR(ROUND((1 - NVL(FREE_SIZE, 0) TOTAL_SIZE) * 100, 2),'FM999990.00') "USED_RATE",
        TO_CHAR(FREE_SPACE,'FM999990.00') "FREE_SPACE",
        TO_CHAR(S.SPLINTER_SPACE,'fm999990.00') "SPLINTER_SPACE",
        TO_CHAR(ROUND((1 - NVL(F.FREE_SIZE-S.SPLINTER, 0) / D.TOTAL_SIZE) * 100, 2),'fm999990.99') "SP_RATE"
    FROM 
      (SELECT TABLESPACE_NAME, SUM(BYTES) TOTAL_SIZE,ROUND(SUM(BYTES) / (1024 * 1024), 2) SPACE, SUM(BLOCKS) BLOCKS FROM DBA_DATA_FILES GROUP BY TABLESPACE_NAME) D,
      (SELECT TABLESPACE_NAME, SUM(BYTES) FREE_SIZE,ROUND(SUM(BYTES) / (1024 * 1024), 2) FREE_SPACE FROM DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F,
      (SELECT TABLESPACE_NAME,COUNT(*) SP_COUNT,SUM(BYTES) SPLINTER,round(sum(bytes)/1024/1024,2) SPLINTER_SPACE FROM DBA_FREE_SPACE WHERE BYTES/1024/1024 <64 GROUP BY TABLESPACE_NAME) S
      WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME(+)
      AND D.TABLESPACE_NAME = S.TABLESPACE_NAME
      ORDER BY  "USED_RATE" DESC) a,
    dba_tablespaces b
  where a.tablespace_name = b.tablespace_name
  and a.tablespace_name not like 'UNDO%';


表空间可用空间不足处理方法

4.1 清理数据

可以清理业务过期数据,释放空间,增加可用空间:
Drop table T1 purge;

4.2 重组表

可以将表重建,重新获取连续空间,降低不连续空间的概率:
Create table t2 as select * from t1;
Drop table t1 purge;
Alter table t2 rename to t1;

4.3 申请扩容表空间

可以提扩容工单,扩容足够表空间防止空间不可用情况:

Alter tablespace tbs1 add datafile ‘+DATAsize 30G;


碎片解决办法

5.1 创建新表空间test_tbs

大小大于需要移动的原表空间:

create tablespace test_tbs datafile '+DATA' SIZE 30G;
Alter tablespace test_tbs add datafile '+DATA' SIZE 30G;
Alter tablespace test_tbs add datafile '+DATA' SIZE 30G;

5.2 移动原表空间内的表

--批量脚本:
SELECT  'alter table '||OWNER||'.'||TABLE_NAME||' move 
tablespace NEW_TABLESPACE;'
 FROM DBA_TABLES WHERE TABLESPACE_NAME = 'OLD_TABLESPACE';

--示例:
alter table U1.T1 move tablespace NEW_TABLESPACE;

如果有分区表:

select 'alter table ' ||table_owner|| '.' || table_name || ' 
move partition '
 || partition_name || ' tablespace
NEW_TABLESPACE;'
 as move_sql from dba_tab_partitions where tablespace_name='OLD_TABLESPACE';

如果有子分区表:

select 'alter table ' ||table_owner|| '.' || table_name || ' 
move subpartition '
 || SUBPARTITION_NAME || ' tablespace
NEW_TABLESPACE;'
 as move_sql from DBA_TAB_SUBPARTITIONS
where tablespace_name='OLD_TABLESPACE';

5.3 查看索引情况

select index_name,index_type,table_name,table_owner,table_type,uniq
ueness,status from dba_indexes where tablespace_name = 'OLD_TABLESPACE';

5.4 重建索引

select 'alter index ' ||OWNER||'.'||index_name||' rebuild 
online;'
 from dba_indexes where status <> 'VALID';

如果有分区索引:

select 'alter index '||a.table_owner||'.' ||b.index_name||' 
rebuild partition '
||a.partition_name||' tablespace
NEW_TABLESPACE parallel 8 online; '
 from dba_tab_partitions
a,dba_ind_partitions b where
a.partition_name=b.partition_name and 
a.tablespace_name='OLD_TABLESPACE';

如果有子分区索引:

select 'alter index '||a.table_owner||'.' ||b.index_name||' 
rebuild subpartition '
||a.partition_name||' tablespace NEW_TABLESPACE parallel 8 online; ' from
dba_tab_subpartitions a,dba_ind_subpartitions b where
a.partition_name=b.partition_name and 
a.subpartition_name=b.subpartition_name and 
a.tablespace_name='OLD_TABLESPACE';

如果有lob字段:

select 'alter table '||owner||'.'||table_name||
' move lob('||COLUMN_NAME||') store as (NEW_TABLESPACE);'from dba_lobs where TABLESPACE_NAME='OLD_TABLESPACE';

如果有需要,可以将这些表,索引等对象重新移动回原表空间内,然后删除中转的表空间;如果直接使用新表空间,可以将原表空间的大小resize回收到ASM磁盘组即可(建议DBA操作)。


END


本文作者:事业二部(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论