ITPub博客

首页 > Linux操作系统 > Linux操作系统 > alter table move跟shrink space的区别

alter table move跟shrink space的区别

原创 Linux操作系统 作者:ciwei_no1 时间:2011-06-21 10:41:03 0 删除 编辑
author:skate
time2010-05-28

--------------------------------------------------------------------------------
http://blog.csdn.net/wyzxg/archive/2010/05/28/5631721.aspx
alter table move跟shrink space的区别
 
今天主要从两点说他们的区别:
1. 碎片的整理
2.空间的收缩
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL>
创建测试表
SQL> create table test3 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;
Table created
SQL> select count(1) from test3;
  COUNT(1)
----------
     10000

查看表test3的blocks使用情况:
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144
PL/SQL procedure successfully completed

制造碎片
SQL> DELETE FROM TEST3 WHERE MOD(ID,3)=1;
3334 rows deleted
SQL> commit;
Commit complete
发现有碎片了
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............1
50% -- 75% free space bytes.............8192
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0
PL/SQL procedure successfully completed
SQL>
消除碎片

SQL> alter table test3 move;
Table altered
查看碎片消除的效果

SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485065
Last Used Block.........................2
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224
PL/SQL procedure successfully completed
SQL>
从以上看,碎片整理的效果很好!!!
下面在测试用shrink整理碎片
重建测试环境

SQL> drop table test3;
Table dropped
SQL>
SQL> create table test3 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;
Table created
查看test3的blocks的使用

SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144
PL/SQL procedure successfully completed
制造碎片

SQL> delete from test3 where mod(id,3)=1;
3334 rows deleted
SQL> commit;
Commit complete
查看碎片情况
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................1
Total bytes.............................8192
PL/SQL procedure successfully completed
用oracle10g新功能整理碎片

SQL> alter table test3 shrink space compact cascade;
alter table test3 shrink space compact cascade
ORA-10636: ROW MOVEMENT is not enabled
SQL> alter table test3 enable row movement;
Table altered
SQL> alter table test3 shrink space compact cascade;
Table altered
再次查看碎片的情况,发现还有一些碎片,整理碎片效果不好

SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
 *************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........12
75% -- 100% free space bytes............98304
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264
PL/SQL procedure successfully completed
上面是没降低HWM,如果载降低HWM,看看效果

SQL> alter table test3 shrink space cascade;
Table altered
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................31
Last Used Ext BlockId...................481897
Last Used Block.........................8
 *************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264
PL/SQL procedure successfully completed
看来用shrink space整理碎片不彻底,再来看看move的方式
SQL> alter table test3 move;
Table altered
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485081
Last Used Block.........................2
 *************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224
PL/SQL procedure successfully completed
效果很明显,整理的很彻底
测试结论:

虽然alter table move和shrink space,都是通过物理调整rowid来整理碎片的,但shrink space整理的不彻底,他好像不是重组,而是尽可能的合并,随意会残留一些block无法整理
注意:
1.再用alter table table_name move时,表相关的索引会失效,所以之后还要执行 alter index index_name rebuild online; 最后重新编译数据库所有失效的对象
2. 在用alter table table_name shrink space cascade时,他相当于alter table table_name move和alter index index_name rebuild online. 所以只要编译数据库失效的对象就可以
alter table move和shrink space除了碎片整理的效果有时不一样外,还有什么其他的不同呢

1. Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。
2. shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作。
下面通过实验来验证

SQL> drop table test3;
Table dropped
SQL>
SQL> create table test3 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;
Table created
SQL> analyze table test3 compute statistics;
Table analyzed
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               5         40
SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3
SQL>

从以上查询可以看出共分了5个extents,使用了37个 blocks,这37也就是test3的HWM
SQL> delete from test3 where rownum<=5000;
5000 rows deleted
SQL> commit;
Commit complete
SQL> analyze table test3 compute statistics;
Table analyzed
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               5         40
SQL> col table_name for a10;
SQL>  select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3
SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from test3;
USED_BLOCKS
-----------
         17

我们从查询中可以发现test3的HWM没有变换还是 37blocks,tests总共空间为40blocks。经过删除后test3实际用的块是17个

下面我们用move降低下HWM
SQL> alter table test3 move;
Table altered
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               3         24
SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              37            3
user_tables里的数据没有变化,哦,原来是忘记analyze了,从这里也可以看出user_segments是oracle自动维护的。
SQL> analyze table test3 compute statistics;
Table analyzed
SQL>  select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA    EXTENTS     BLOCKS
---------- ---------- ----------
TEST3               3         24
SQL> select table_name,blocks,t.empty_blocks  from user_tables t where t.table_name=upper('test3');
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3              20            4
SQL>

现在再来看hwm变为20了,已经降下来了啊,空间也收缩了,从40blocks降到24blocks(注意收缩到initial指定值)。
但shrink space就收缩到存储数据的最小值,下面测试说明
创建测试表:

SQL>   create table test5 (id number) storage (initial 1m next 1m);
Table created
初始化数据

SQL>
SQL>   begin
  2     for i in 1..100000 loop
  3     insert into test5 values(i);
  4    end loop;
  5    end;
  6  /
PL/SQL procedure successfully completed
SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              17        256          1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5             180           76
可以从查询数据看出,test5初始化1m即128个blocks,但数据比较多,所以又按next参数要求扩展了1m空间,扩展了17个extents。
这里的test5总空间大小为256个blocks,使用空间为180blocks,HWM也是180blocks

SQL> delete from test5 where rownum<=50000;
50000 rows deleted
SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              17        256          1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5             180           76
整理碎片,降低HWM

SQL>  alter table test5 move;
Table altered

SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              16        128          1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5              85           43
从上面的查询数据可以看出HWM已经从180降低到85,test5 总大小从256blocks收缩到128个blocks(initial指定大小)。

下面看看用shrink space收缩空间的情况
SQL> alter table test5 enable row movement;
Table altered

SQL> alter table test5 shrink space;
Table altered
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA    EXTENTS     BLOCKS       INIT
---------- ---------- ---------- ----------
TEST5              11         88          1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME     BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5              85           43
SQL>

从上面的数据可以看到test5进一步从128个blocks降低到88个blocks
结论:

shrink space收缩到数据存储的最小值,alter table move(不带参数)收缩到initial指定值,也可以用alter table test5 move storage(initial 500k)指定收缩的大小,这样可以达到shrink space效果
经过以上测试,得出的两个结论,到底用哪一个命令来整理碎片,消除行迁移呢?这就要根据实际业务需要,如果你只是收缩空间,数据增长很慢,那用shrink可以但是如果数据增长很快的话,用move就比较合适,避免再重新分配空间啊
备注:
在10g之后,整理碎片消除行迁移的新增功能shrink space
alter table shrink space [ | compact | cascade ];
compact :这个参数当系统的负载比较大时可以用,不降低HWM。如果系统负载较低时,直接用alter table table_name shrink space就一步到位了

cascade :这个参数是在shrink table的时候自动级联索引,相当于rebulid index。
普通表:

shrink必须开启行迁移功能。
alter table table_name enable row movement ;
保持HWM,相当于把块中数据打结实了
alter table table_name shrink space compact;
回缩表与降低HWM
alter table table_name shrink space;
回缩表与相关索引,降低HWM
alter table table_name shrink space cascade;
回缩索引与降低HWM
alter index index_name shrink space
虽然在10g中可以用shrink ,但也有些限制:
1). 对cluster,cluster table,或具有Long,lob类型列的对象 不起作用。
2). 不支持具有function-based indexes 或 bitmap join indexes的表
3). 不支持mapping 表或index-organized表。
4). 不支持compressed 表
------end------
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangdeng1314/archive/2010/07/15/5735768.aspx

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22980662/viewspace-700361/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 不开心
请登录后发表评论 登录
全部评论

注册时间:2010-12-29

  • 博文量
    24
  • 访问量
    55439