【转载】alter table move 和 alter table shrink space的区别

move 和shrink 的共同点
1、收缩段
2、消除部分行迁移
3、消除空间碎片
4、使数据更紧密

shrink



语法:
  alter table TABLE_NAME shrink space [compact|cascate]

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释放空闲数据块。



举例

  alter table TABLE_NAME shrink space compact;  只整理碎片 不回收空间,  
  alter table TABLE_NAME shrink space;                 整理碎片并回收空间。

  alter table TABLE_NAME shrink space cascade;    整理碎片回收空间 并连同表的级联对象一起整理(比如索引)
  --分区表
  alter table ticket modify  PARTITION P28071 shrink space cascade


shrink的优点
1.可在线执行
2.可使用参数cascade,同时收缩表上的索引
3.执行后不会导致索引失效
4.可避免alter table move执行过程中占用很多表空间(如果表10G大小,那alter table move差不多还得需要10G空间才能执行)。

shrink 使用条件:
使用步骤
  1. alter table t1 enable  ROW MOVEMENT;
  2. shrink 操作
  3. alter table t1 disable  ROW MOVEMENT;

shrink使用限制:
Shrink 操作需满足表空间是本地管理和自动段空间管理(10g、11g默认就是这样),
以下情况不能用shrink:

IOT索引组织表
用rowid创建的物化视图的基表
带有函数索引的表
SECUREFILE 类型的大对象
压缩表



move



move解决的问题
1、将一个table从当前的tablespace上移动到另一个tablespace上:

alter table t move tablespace tablespace_name;
alter table TABLE_NAME move ;                                                    --在原来的表空间内部移动。

2、来改变table已有的block的存储参数,如:

    alter table t move storage (initial 30k next 50k);

3、另外,move操作也可以用来解决table中的行迁移的问题。

使用move的一些注意事项:
1、table上的index需要rebuild:
    在前面我们讨论过,move操作后,数据的rowid发生了改变,我们知道,index是通过rowid来fetch数据行的,所以,table上的index是必须要rebuild的。
    alter index index_name rebuild online;
2、move时对table的锁定
    当我们对table进行move操作时,查询v$locked_objects视图可以发现,table上加了exclusive lock
3、关于move时空间使用的问题:
    当我们使用alter table move来降低table的HWM时,有一点是需要注意的,这时,当前的tablespace中需要有1倍于table的空闲空间以供使用。


move和hrink的区别是:
1、move后,表在表空间中的位置肯定会变,可能前移也可能后移,一般来说如果该表前面的表空间中有足够空间容纳该表,则前移,否则后移。
2、hrink后,表在表空间中的位置肯定不变,也就是表的段头位置不会发生变化。

3、Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。
4、shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作。

5、使用move时,会改变一些记录的ROWID,所以MOVE之后索引会变为无效,需要REBUILD。
6、使用shrink space时,索引会自动维护。如果在业务繁忙时做压缩,
    可以先shrink space compact,来压缩数据而不移动HWM,等到不繁忙的时候再shrink space来移动HWM。


7、shrink可以单独压缩索引,alter index xxx shrink space来压缩索引。另外、压缩表时指定Shrink space cascade会同时压缩索引,




测试

SQL> 
SQL> drop table  test  purge;
SQL> drop table  test2        purge;
SQL> 
SQL> create table test (id number) storage (initial 10m next 1m) tablespace users;
SQL> create table test2 (id number) storage (initial 10m next 1m) tablespace users;
SQL> 
SQL> insert into test values(1);
SQL> insert into test2 values(1);
SQL> 
SQL> analyze table test compute statistics;
SQL> analyze table test2 compute statistics;
SQL> 
SQL> col SEGMENT_NAME for a10;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME in ('TEST','TEST2');
SEGMENT_NA                                EXTENTS                                 BLOCKS                                   INIT
---------- -------------------------------------- -------------------------------------- --------------------------------------
TEST2                                           3                                   1280                                     10
TEST                                            3                                   1280                                     10
--两个表,原始申请的分区数和数据块数
SQL> col TABLE_NAME for a10;
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name in ('TEST','TEST2');
TABLE_NAME                                 BLOCKS                           EMPTY_BLOCKS
---------- -------------------------------------- --------------------------------------
TEST                                           46                                   1234
TEST2                                          46                                   1234
--两个表,实际使用的数据块数46,空闲数据块数1234。
SQL> 
SQL> begin
  2   for i in 1..100000 loop
  3  insert into test values(i);
  4  insert into test2 values(i);
  5  end loop;
  6  end;
  7  /
SQL> 
SQL> analyze table test compute statistics;
SQL> analyze table test2 compute statistics;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME in ('TEST','TEST2');
SEGMENT_NA                                EXTENTS                                 BLOCKS                                   INIT
---------- -------------------------------------- -------------------------------------- --------------------------------------
TEST2                                           3                                   1280                                     10
TEST                                            3                                   1280                                     10
--插入大量数据后,两个表的原始申请分区数和数据块数,没有变化
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name in ('TEST','TEST2');
TABLE_NAME                                 BLOCKS                           EMPTY_BLOCKS
---------- -------------------------------------- --------------------------------------
TEST                                          174                                   1106
TEST2                                         174                                   1106
--插入大量数据后,两个表实际使用的数据块数发生了变化,使用174块,空闲1106块。174就是高水位线
SQL> 
SQL> 
SQL> delete from test where rownum<=50000;
SQL> delete from test2 where rownum<=50000;
SQL> 
SQL> analyze table test compute statistics;
SQL> analyze table test2 compute statistics;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME in ('TEST','TEST2');
SEGMENT_NA                                EXTENTS                                 BLOCKS                                   INIT
---------- -------------------------------------- -------------------------------------- --------------------------------------
TEST2                                           3                                   1280                                     10
TEST                                            3                                   1280                                     10
--删除大量数据后,两个表的原始申请分区数和数据块数,没有变化


SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name in ('TEST','TEST2');
TABLE_NAME                                 BLOCKS                           EMPTY_BLOCKS
---------- -------------------------------------- --------------------------------------
TEST                                          174                                   1106
TEST2                                         174                                   1106
--删除大量数据后,两个表实际使用的数据块数也没有发生变化。即delete不会释放空间


SQL> 
SQL> 
SQL> alter table test move;
SQL> 
SQL> analyze table test compute statistics;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME in ('TEST','TEST2');
SEGMENT_NA                                EXTENTS                                 BLOCKS                                   INIT
---------- -------------------------------------- -------------------------------------- --------------------------------------
TEST2                                           3                                   1280                                     10
TEST                                            3                                   1280                                     10
--对test表,做move操作,原始申请分区和数据块数,没有变化。


SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name in ('TEST','TEST2');
TABLE_NAME                                 BLOCKS                           EMPTY_BLOCKS
---------- -------------------------------------- --------------------------------------
TEST                                           95                                   1185
TEST2                                         174                                   1106
--对test表,做move操作,实际使用数据块数发生变化。
Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。


SQL> 
SQL> 
SQL> alter table test2 enable row movement;
SQL> alter table test2 shrink space;
SQL> analyze table test2 compute statistics;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME in ('TEST','TEST2');
SEGMENT_NA                                EXTENTS                                 BLOCKS                                   INIT
---------- -------------------------------------- -------------------------------------- --------------------------------------
TEST2                                           1                                    104                                     10
TEST                                            3                                   1280                                     10
--对test2表,做shrink操作,原始申请分区和数据块数,发生了变化
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name in ('TEST','TEST2');
TABLE_NAME                                 BLOCKS                           EMPTY_BLOCKS
---------- -------------------------------------- --------------------------------------
TEST                                           95                                   1185
TEST2                                          79                                     25
--对test2表,做shrink操作,实际使用数据块数,发生了变化
shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作。


SQL> spool off;

原文出处:http://www.itpub.net/thread-1866952-1-1.html

原文地址:https://www.cnblogs.com/hankyoon/p/5174578.html