alter table move跟shrink space的區別

maojinyu發表於2010-09-29

  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/10 24 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/10 24 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/10 24 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/10 24 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 表

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9907339/viewspace-1039104/,如需轉載,請註明出處,否則將追究法律責任。

相關文章