您的位置:首页 > 其它

alter table move跟shrink space的区别

2016-03-22 13:40 375 查看
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 movestorage(initial
500k)指定收缩的大小,这样可以达到shrink space效果

 

 

 

经过以上测试,得出的两个结论,到底用哪一个命令来整理碎片,消除行迁移呢?这就要根据实际业务需要,如果你只是收缩空间,数据增长很慢,那用shrink可以但是如果数据增长很快的话,用move就比较合适,避免再重新分配空间啊

 

 

 

备注:

在10g之后,整理碎片消除行迁移的新增功能shrink space

 

alter table <table_name> shrink space [ <null> | 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------

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  move shrink