在生产中经常会遇到频繁更新的表,时间久了之后就会产生较多的碎片。
产生的碎片的根本原因就是因为表上dml较多,导致出现这种情况最操蛋的原因就是开发在处理表时不严谨。
比如在全量同步表时候,经常性的操作就是delete from t ;insert into t;然后循环往复。
正确的做法是truncate table t ;insert into t ;
以上只是背景,最重要的是问题出现了,我们怎么去处理这种情况。
对于Oracle来说,处理表碎片的方式有:
1、shrink space
2、move tablespace
3、导入导出
4、cats
5、在线重定义
这篇主要记录下有关alter table ... shrink来回收表碎片的问题
有两种方式:
alter table table_name shrink space ;
alter table table_name shrink space compact;
对于alter table shrink ,很多人疑问的是,我使用shrink table回收了表碎片,但是数据文件和表空间的空间貌似没有任何变化。这其实是对shrink table的原理不理解导致的。
shrink table只是针对表本身,而数据文件的空间在创建表空间或者数据文件的时候就已经确定了。
使用shrink的限制:
a、alter table ... shrink语句不能结合其他alter table语句使用
b、不能用于clustered table或者任何有long属性列的表
c、不支持基于函数索引、域索引及位图索引的表
d、不能用于压缩表
e、不能用于on commit物化视图的主表,Rowid物化视图必须在收缩操作后重新生成
操作:
在使用alter table shrink之前,需要开启表的行移动属性
alter table table_name enable row movement ;
alter table table_name shrink space ;(整理碎片并回收空间)
alter table table_name shrink space compact;(只整理碎片,不回收空间)
alter table table_name disable row movement ;
完成之后不需要重建索引,做完之后收集统计信息。
cascade:缩小表及其索引,并移动高水位线,释放空间
compact:仅仅是缩小表和索引,并不移动高水位线,不释放空间
alter table table_name shrink space 相当于带cascade参数
总结:
alter table ... shrink需要满足:
表位于Locally Managed Tablespace(本地管理表空间),以便自动段空间管理可用
表所在的表空间必须使用Automatic Segment Space Management(自动段空间管理)
select t.SEGMENT_SPACE_MANAGEMENT,t.EXTENT_MANAGEMENT,t.* from dba_tablespaces t
表的row movement属性必须开启(除非是索引组织表)
==============================
相关脚本:
查看位于ASSM表空间的表的空闲空间
The following process may be used at any time to determine the amount of free space within a table in an ASSM tablespace
注意在使用时将<SCHEMA>、<OBJECT NAME>、<OBJECT TYPE>替换为你的实际值
set serveroutput on
declare
TOTAL_BLOCKS number;
TOTAL_BYTES number;
UNUSED_BLOCKS number;
UNUSED_BYTES number;
LAST_USED_EXTENT_FILE_ID number;
LAST_USED_EXTENT_BLOCK_ID number;
LAST_USED_BLOCK number;
begin
dbms_space.unused_space(
'<SCHEMA>',
'<OBJECT NAME>',
'<OBJECT TYPE>',
TOTAL_BLOCKS,
TOTAL_BYTES,
UNUSED_BLOCKS,
UNUSED_BYTES,
LAST_USED_EXTENT_FILE_ID,
LAST_USED_EXTENT_BLOCK_ID,
LAST_USED_BLOCK);
dbms_output.put_line('TOTAL_BLOCKS = '||TOTAL_BLOCKS);
dbms_output.put_line('UNUSED_BLOCKS = '||UNUSED_BLOCKS);
end;
/
The following procedure may be used at any time to see the block allocations for a table stored in an ASSM tablespace
注意在使用时将<SCHEMA>、<OBJECT NAME>、<OBJECT TYPE>替换为你的实际值
set serveroutput on
declare
v_unformatted_blocks number;
v_unformatted_bytes number;
v_fs1_blocks number;
v_fs1_bytes number;
v_fs2_blocks number;
v_fs2_bytes number;
v_fs3_blocks number;
v_fs3_bytes number;
v_fs4_blocks number;
v_fs4_bytes number;
v_full_blocks number;
v_full_bytes number;
begin
dbms_space.space_usage (
'<SCHEMA>',
'<OBJECT NAME>',
'<OBJECT TYPE>',
v_unformatted_blocks,
v_unformatted_bytes,
v_fs1_blocks,
v_fs1_bytes,
v_fs2_blocks,
v_fs2_bytes,
v_fs3_blocks,
v_fs3_bytes,
v_fs4_blocks,
v_fs4_bytes,
v_full_blocks,
v_full_bytes);
dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
dbms_output.put_line('Blocks with 00-25% free space = '||v_fs1_blocks);
dbms_output.put_line('Blocks with 26-50% free space = '||v_fs2_blocks);
dbms_output.put_line('Blocks with 51-75% free space = '||v_fs3_blocks);
dbms_output.put_line('Blocks with 76-100% free space = '||v_fs4_blocks);
dbms_output.put_line('Full Blocks = '||v_full_blocks);
end;
/
参考文档:
Why is no space released after an ALTER TABLE ... SHRINK? (Doc ID 820043.1) |