对比shrink和move

     最近整理了一下系统内所有表的空间占用情况,发现其中一些表其实只有及万行,却占用了非常大的空间,那么显而易见,这个表的“碎片”实在是太多了。

     最开始接触oracle的时候我认为删除数据就是delete,但是后来的学习中,发现事情并不是我想象的那么简单,delete之后,系统也只是将这部分数据块置为可写状态,而实际上还是将这部分空间交由表来占用。而我发现我们系统中为了提高插入的效率,大量的使用了append方式,这样就更加积重难返了。

     可以设计下面的实验:

     有两个表test1和test2。

     

create table test1 as select * from dba_objects;
create table test2 as select * from dba_objects;
delete from test1;
commit;
delete from test2;
commit;
insert /*+append*/ into test1 select * from dba_objects;
commit;
insert into test2 select * from dba_objects;
commit;

   这样子,test1里就会有“碎片”了,而TEST2则是一个比较健康的表。占用空间为test1:17M,TEST2:9M。

       现在就可以对比对比执行计划了:

       

analyze table test1 compute statistics;
analyze table test2 compute statistics;

  

      

      一样大的两张表,执行计划却有比较大的差异,在这种小数据量的情况下尚能看出差异,那么在生产系统中动辄上百万千万的数据量,这个效率差异会更加明显。

     这些表在我们的系统中会每天都被delete一次,delete的效率也严重的被“碎片”影响着:

     delete * from test1;

     

     delete * from test2;

     

    其实这个和上面的select是一样的,都是全表扫描,索引COST基本上和刚才的select语句一样。

    这里写到的东西大部分在http://www.cnblogs.com/wingsless/archive/2013/03/13/2957554.html这里都写过了,这里就想说明一下对delete也有影响,也顺便在后面说几句shrink。

    以前单位的总部曾经来过一个专家给我们指导过工作,告诉我们,有些表应该shrink一下了。之前已经说了,shrink的好处就是不会改变rowid,所以索引不会失效。还是刚才的test1,加上索引,进行shrink操作:

   

alter table test1 enable row movement;
alter table test1 shrink space;

     这样操作之后test1占用的空间就只有8.25M,再看看索引的状态:VALID。这是个很不错的消除表“碎片”的办法,值得在以后的工作中使用之。

原文地址:https://www.cnblogs.com/wingsless/p/3000581.html