Shrink space合并表的碎片

一般表里有碎片我们都采用alter table table_name move tablespace_name,或者exp,drop table table_name,imp的2种方式10G给我们其他的方法.下面我来试一吧
 

C:\Documents and Settings\Administrator>sqlplus greatfinish/finish
SQL*Plus: Release 10.2.0.1.0 - Production on 星期一 7月 3 23:34:22 2006
Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
greatfinish@TEST> drop table t;
表已删除。
--创建测试表
greatfinish@TEST> create table t as
  2  select rownum id,
  3  dbms_random.string('a', round(dbms_random.value(0,10))) col1,
  4  trunc(sysdate) - dbms_random.value(1, 365*2) col2
  5  from dual connect by rownum<=10000;
表已创建。
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               0
FS2 Blocks (25-50) .....................               0
FS3 Blocks (50-75) .....................               0
FS4 Blocks (75-100).....................               0
Full Blocks        .....................              32
Total Blocks............................              40
Total Bytes.............................         327,680
Total MBytes............................               0
Unused Blocks...........................               3
Unused Bytes............................          24,576
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           1,993
Last Used Block.........................               5
PL/SQL 过程已成功完成。
--构造碎片
greatfinish@TEST> delete from t where mod (id,3)=1;
已删除3334行。
greatfinish@TEST> commit;
提交完成。
--发现碎片
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               0
FS2 Blocks (25-50) .....................              31
FS3 Blocks (50-75) .....................               0
FS4 Blocks (75-100).....................               0
Full Blocks        .....................               1
Total Blocks............................              40
Total Bytes.............................         327,680
Total MBytes............................               0
Unused Blocks...........................               3
Unused Bytes............................          24,576
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           1,993
Last Used Block.........................               5
PL/SQL 过程已成功完成。
--9i和之前版本的方法
greatfinish@TEST> alter table t move;
表已更改。
--效果是明显的
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               0
FS2 Blocks (25-50) .....................               0
FS3 Blocks (50-75) .....................               0
FS4 Blocks (75-100).....................               0
Full Blocks        .....................              22
Total Blocks............................              32
Total Bytes.............................         262,144
Total MBytes............................               0
Unused Blocks...........................               6
Unused Bytes............................          49,152
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           2,025
Last Used Block.........................               2
PL/SQL 过程已成功完成。
greatfinish@TEST> drop table t;
表已删除。
greatfinish@TEST> create table t as
  2  select rownum id,
  3  dbms_random.string('a', round(dbms_random.value(0,10))) col1,
  4  trunc(sysdate) - dbms_random.value(1, 365*2) col2
  5  from dual connect by rownum<=10000;
表已创建。
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               0
FS2 Blocks (25-50) .....................               0
FS3 Blocks (50-75) .....................               0
FS4 Blocks (75-100).....................               0
Full Blocks        .....................              32
Total Blocks............................              40
Total Bytes.............................         327,680
Total MBytes............................               0
Unused Blocks...........................               3
Unused Bytes............................          24,576
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           1,993
Last Used Block.........................               5
PL/SQL 过程已成功完成。
greatfinish@TEST> delete from t where mod (id,3)=1;
已删除3334行。
greatfinish@TEST> commit;
提交完成。
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               0
FS2 Blocks (25-50) .....................              31
FS3 Blocks (50-75) .....................               1
FS4 Blocks (75-100).....................               0
Full Blocks        .....................               0
Total Blocks............................              40
Total Bytes.............................         327,680
Total MBytes............................               0
Unused Blocks...........................               3
Unused Bytes............................          24,576
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           1,993
Last Used Block.........................               5
PL/SQL 过程已成功完成。
--10G的方法使用alter table table_name shrink space compact cascade
greatfinish@TEST> alter table t enable row movement;
表已更改。
greatfinish@TEST> alter table t shrink space compact cascade;
表已更改。
--效果并不明显
greatfinish@TEST> exec show_space('T');
Unformatted Blocks .....................               0
FS1 Blocks (0-25)  .....................               1
FS2 Blocks (25-50) .....................               2
FS3 Blocks (50-75) .....................               0
FS4 Blocks (75-100).....................              12
Full Blocks        .....................              17
Total Blocks............................              40
Total Bytes.............................         327,680
Total MBytes............................               0
Unused Blocks...........................               3
Unused Bytes............................          24,576
Last Used Ext FileId....................               4
Last Used Ext BlockId...................           1,993
Last Used Block.........................               5
PL/SQL 过程已成功完成。
greatfinish@TEST> select block_num,count(*) from
  2  (select dbms_rowid.rowid_block_number(rowid) block_num from t)
  3  group by block_num;
 BLOCK_NUM   COUNT(*)
---------- ----------
      1956        352
      1957        352
      1958        351
      1959        346
      1960        351
      1961        349
      1962        349
      1963        350
      1964        351
      1965        352
      1966        353
      1967        354
      1968        350
      1970        347
      1971        348
      1972        353
      1973        348
      1974        288
      1975        212
      1976        210
已选择20行。
greatfinish@TEST>
 
结论说明alter table table_name shrink space compact cascade只合并了部分extents,并没有真正意义上的把数据进行整理.效果没有imp,exp和move好.以后还是用之前的两种来做比较好
 
 

Oracle 10g

语法:

alter table <table_name> shrink space [ <null> | compact | cascade ];

alter table <table_name> shrink space compcat;

收缩表,但会保持 high water mark; (这怎么理解?相当于没回缩?)

alter table <table_name> shrink space;

收缩表,降低 high water mark;

alter table <table_name> shrink space cascade;

收缩表,降低 high water mark,并且相关索引也要收缩一下下。


shrink space compcat;
相当于把块中数据打结实了。没有变动hwm。

 

 方法一:
Export/Truncate/Import
方法二:
alter table table_name move; alter index index_name rebuild;
这两种方法,哪种更好?我个人觉得方法二更方便。


如果方便的話,就用第二种。個人一直用的第二种方式!
前面提到oracle在10g已有專用的命令來做此動作了,如下:
alter table table_name shrink space;
後面還有兩個參數:cascade,compact;
compact:加此參數是爲了黨系統負載比較大時,做此動作可以減小性能影響。在負載比較輕時,在作一次alter table table_name shrink space;就可以了。
cascade:加上此參數會及聯shrink table上的索引,也相當如rebuild index; 也就相當於你上面在9i裏處理此問題的第二种方式了!

所以第二种方式是完全可行的,只是要關注做此動作時對性能的影響。一般在系統負載比較輕時做此動作。另rebuild online時,會lock table。此時會影響系統dml操作,因此可以在語句后加online來降低影響,但會增加rebuil時間。總計,均衡當前狀況,來採取最合理的方式!

 

我发现一个问题:
如果 执行  ALTER TABLE xxx MOVE;  后 还没有来的及执行  ALTER INDEX xxx REBUILD;  
就有人对 该表进行了查询或更新,
那么就会报错;
有没有办法在ALTER TABLE xxx MOVE的时候,该表还能正常被使用,这样就不用担心用在执行上面那个批量整理脚本的时候,数据库一些表访问会报错;


因爲alter table ... move,會使得此表上的索引失效,此時,會使得利用索引訪問此表的sql語句報錯。因此,此動作一般是不會經常做的,也沒這個必要,也不會寫在腳本裏自動執行,還是在系統負載較輕時,手動維護比較好!
另做此動作后,注意重新分析下此表及對應索引!

补充:ALTER TABLE xxx MOVE将导致rowid改变,而索引是根据rowid来访问的,所以会出错。

1:普通表

shrink必须开启行迁移功能。

alter table table_name enable row movement ;

保持HWM
alter table table_name shrink space compact;

回缩表与HWM
alter table table_name shrink space;

回缩表与相关索引
alter table table_name shrink space cascade;

回缩索引
alter index index_name shrink space;

Sql脚本

select'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)fromuser_tables;

select'alter index '||index_name||' shrink space;'||chr(10)fromuser_indexes;

 

2分区表的处理

进行shrink space时 发生ORA-10631错误.shrink space有一些限制.

在表上建有函数索引(包括全文索引)会失败。

 

sql脚本

select 'alter table '||segment_name||' modify subpartition '||partition_name||' shrink space;'||chr(10) from user_segments where segment_type='TABLE SUBPARTITION'

脚本

执行方法cmd

        C:"cd到放置两个文件的文件夹

        Sqlplus username/password@oracle_sid

        Sql>@sp.sql

 

@@sp.sql

 

set heading off

set feedback off

set term off

set page off

set trimspool on

spool a.log

@a.sql

spool off

@@a.log /*慎重,估计好执行时间再执行,也可以手动执行脚本*/

Exit

 

@@a.sql

 

select 'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10) from user_tables where table_name ;

select 'alter index '||index_name||' shrink space;'||chr(10) from user_indexes where uniqueness='NONUNIQUE' ;

select 'alter table '||segment_name||' modify subpartition '||partition_name||' shrink space;'||chr(10) from user_segments where segment_type='TABLE SUBPARTITION' ';

posted on 2009-02-01 00:10  一江水  阅读(6016)  评论(0编辑  收藏  举报