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

Oracle空间回收

原创 ziyoo0830 2019-12-31
5252

Oracle空间回收

1、总述

在Oracle数据库中,在对表数据进行大量delete操作后,高水位不会自动回收,需要对表进行shrink,以提高查询效率,同时可以考虑对数据文件进行resize,以减少数据库总大小;

2、对表进行shrink

2.1、原理

segment shrink分为两个阶段:

1)、数据重组(compact):通过一系列insert、delete操作,将数据尽量排列在段的前面。在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。由于涉及到rowid的改变,需要enable row movement.同时要disable基于rowid的trigger,这一过程对业务影响比较小。

2)、HWM调整:第二阶段是调整HWM位置,释放空闲数据块。此过程需要在表上加X锁,会造成表上的所有DML语句阻塞。在业务特别繁忙的系统上可能造成比较大的影响。

shrink space 语句两个阶段都执行。

shrink space compact 只执行第一个阶段。

如果系统业务比较繁忙,可以先执行shrink space compact重组数据,然后在业务不忙的时候再执行shrink space降低HWM释放空闲数据块。

shrink必须开启行迁移功能。

alter table table_name enable row movement ;

对于包含大字段的表,需要使用如下命令进行收缩;

alter table table_name modify lob(lob_column) (shrink space cascade) ;
复制

**或者使用在线重定义的方式进行空间收缩(可参考文档 **Doc ID 1394613.1);

2.1.1、命令汇总

alter table table_name enable row movement ; alter table table_name shrink space compact ; alter table table_name shrink space cascade ; --加cascade,表上相应的索引也会同时进行收缩。
复制

2.2、自动段统计信息收集

在开启了自动统计信息收集后,oracle会自动给出段建议,同时给出相应的收缩命令,可以参考如下脚本输出:

select tablespace_name, segment_name, segment_type, partition_name, recommendations, regexp_substr(recommendations, '\d{1,}', 1) / 1024 / 1024 / 1024 sizef, c1 from table(dbms_space.asa_recommendations('FALSE', 'FALSE', 'FALSE')) order by sizef desc;
复制

2.3、注意

收缩时会有大量的归档的日志产生,要保证有足够的归档空间;

2.4、批量收缩脚本样例

对表进行收缩,如果表中含有lob字段,同时收缩lob;

create or replace procedure shrink authid current_user as v_shrink_sql varchar2(32767); v_shrink_lob_sql varchar2(32767); v_error_code VARCHAR2(10); --错误码 v_description VARCHAR2(160); --错误信息 cursor cur_shrinks is select t.owner, t.table_name from dba_tables t; cursor cur_lobs(v_owner varchar2, v_table_name varchar2) is select t.OWNER, t.TABLE_NAME, t.COLUMN_NAME, t.DATA_TYPE from dba_tab_columns t where t.DATA_TYPE = 'CLOB' and t.OWNER = v_owner and t.TABLE_NAME = v_table_name; begin dbms_output.enable(buffer_size => null); for cur_shrink in cur_shrinks loop v_shrink_sql := 'alter table ' || cur_shrink.owner || '.' || cur_shrink.table_name || ' shrink space cascade '; dbms_output.put_line(v_shrink_sql || ';'); begin execute immediate v_shrink_sql; exception when others then v_error_code := SQLCODE; v_description := substr(sqlerrm, 1, 560); dbms_output.put_line(v_error_code || ';' || v_description); dbms_output.put_line('>>> error ' || v_shrink_sql); end; for cur_lob in cur_lobs(cur_shrink.owner, cur_shrink.table_name) loop v_shrink_lob_sql := 'alter table ' || cur_lob.owner || '.' || cur_lob.table_name || ' modify lob(' || cur_lob.column_name || ') (shrink space cascade) '; dbms_output.put_line(v_shrink_lob_sql || ';'); begin execute immediate v_shrink_lob_sql; exception when others then v_error_code := SQLCODE; v_description := substr(sqlerrm, 1, 560); dbms_output.put_line(v_error_code || ';' || v_description); dbms_output.put_line('>>> error ' || v_shrink_lob_sql); end; end loop; end loop; end;
复制

3、对数据文件进行resize

在对表进行shrink后,可以考虑对数据文件进行resize;可使用如下脚本列出resize语句;

with hwm as ( -- get highest block id from each datafiles ( from x$ktfbue as we don't need all joins from dba_extents ) select /*+ materialize */ ktfbuesegtsn ts#,ktfbuefno relative_fno,max(ktfbuebno+ktfbueblks-1) hwm_blocks from sys.x$ktfbue group by ktfbuefno,ktfbuesegtsn ), hwmts as ( -- join ts# with tablespace_name select name tablespace_name,relative_fno,hwm_blocks from hwm join v$tablespace using(ts#) ), hwmdf as ( -- join with datafiles, put 5M minimum for datafiles with no extents select file_name,nvl(hwm_blocks*(bytes/blocks),5*1024*1024) hwm_bytes,bytes,autoextensible,maxbytes from hwmts right join dba_data_files using(tablespace_name,relative_fno) ) select case when autoextensible='YES' and maxbytes>=bytes then -- we generate resize statements only if autoextensible can grow back to current size '/* reclaim '||to_char(ceil((bytes-hwm_bytes)/1024/1024),999999) ||'M from '||to_char(ceil(bytes/1024/1024),999999)||'M */ ' ||'alter database datafile '''||file_name||''' resize '||ceil(hwm_bytes/1024/1024)||'M;' else -- generate only a comment when autoextensible is off '/* reclaim '||to_char(ceil((bytes-hwm_bytes)/1024/1024),999999) ||'M from '||to_char(ceil(bytes/1024/1024),999999) ||'M after setting autoextensible maxsize higher than current size for file ' || file_name||' */' end SQL from hwmdf where bytes-hwm_bytes>1024*1024 -- resize only if at least 1MB can be reclaimed order by bytes-hwm_bytes desc
复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
3人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

章芋文
暂无图片
5年前
评论
暂无图片 1
好久不见,😊
5年前
暂无图片 1
评论