ALTER TABLE MOVE和SHRINK SPACE區別

suphy23發表於2012-10-24


Alter table move或者shrink space可以收縮段,消除部分行遷移、消除空間碎片、使資料更緊密,但moveshrink space還是有區別的。

       Move會移動高水位,但不會釋放申請的空間,是在HWM以下的操作

       Shrink space同樣會移動hwm但也會釋放申請的空間,是在hwm上下都有的操作。

SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle Database Enterprise Edition Release 10.2.0.4.0 - Prod

PL/SQL Release 10.2.0.4.0 - Production

CORE   10.2.0.4.0     Production

TNS for Linux: Version 10.2.0.4.0 - Production

NLSRTL Version 10.2.0.4.0 - Production 

首先用alter table move方式:

建立測試表

SQL> create table test(id number) storage(initial 10m next 1m) tablespace scott_test;
Table created.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> select table_name,blocks,empty_blocks from user_tables
  2  where table_name='TEST';
TABLE_NAME    BLOCKS   EMPTY_BLOCKS
--------------------- ------------------ -------------------------
TEST               0        1280

SQL> select segment_name,extents,blocks from user_segments
2  where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS

--------------------- ------------------- ---------------
TEST              10         1280

SQL> begin 
 2    for i in 1..100000 loop
 3    insert into test values(i);
 4    end loop;
 5 end;
 6 /

SQL> analyze table test compute statistics; --
test表操作後,只有對該表做過分析後(compute statistics),資料字典才會記錄該表修改後的狀態
Table analyzed.

SQL> col segment_name format a20

SQL> select table_name,blocks,empty_blocks from user_tables 
 2  where table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST             186        1094   --空閒塊降低了

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ----------
TEST              10      1280

插入10萬行後,分配空間沒變,分配的10extents並未使用完,使用了186blocks,空閒1094blocks,此時hwm186

SQL> delete from test where rownum <=50000;  --刪除一半的資料
50000 rows deleted.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> select table_name,blocks,empty_blocks from user_tables
  2  where table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST             186        1094

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ----------
TEST              10      1280

SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks
2  from test;

USED_BLOCKS
-----------
        77

刪除一半資料後仍然使用186blocks,而真正使用了77blocksHwm不變。

SQL> alter table test move;
Table altered.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> select table_name,blocks,empty_blocks from user_tables
 2   where table_name='TEST';
TABLE_NAME    BLOCKS  EMPTY_BLOCKS
---------- ---------- ------------
TEST              81        1199    --move後,空閒塊增加了,hwm降低了

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ----------
TEST              10      1280   --但分配空間並沒有降低

move後,空閒塊增加了,hwm降低了,但分配空間並沒有降低。

使用alter table shrink space方式:

SQL> create table test(id number) storage(initial 10m next 1m) tablespace scott_test;
Table created.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> col segment_name for a10

SQL> select table_name,blocks,empty_blocks from user_tables where
 2  table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST               0        1280 

SQL> select segment_name,extents,blocks from user_segments

 2  where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ---------- ----------
TEST              10      1280

SQL> begin
 2    for i in 1..100000 loop
 3    insert into test values(i);
 4    end loop;
 5 end;
 6 /
PL/SQL procedure successfully completed.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> select table_name,blocks,empty_blocks from user_tables
 2 where table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST             186        1094

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ----------
TEST              10      1280

SQL> delete from test where rownum<=50000;
50000 rows deleted.

SQL> select table_name,blocks,empty_blocks from user_tables
 2 where table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
----------------------- --------------- ---------------------
TEST             186        1094

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------------------- ----------------- -----------------
TEST              10       1280

SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from test;
USED_BLOCKS
-----------
        77

SQL> alter table test enable row movement;
Table altered.

SQL> alter table test shrink space;
Table altered.

SQL> analyze table test compute statistics;
Table analyzed.

SQL> select table_name,blocks,empty_blocks from user_tables
  2  where table_name='TEST';
TABLE_NAME    BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST              79           9   --shrink space後,空閒減少了,hwm降低了

SQL> select segment_name,extents,blocks from user_segments
 2 where segment_name='TEST';
SEGMENT_NA   EXTENTS    BLOCKS
---------- ---------- ----------
TEST               1        88     --同時分配空間也降低了

透過上面比較,move不算真正意義上的壓縮空間,只會壓縮HWM以下的空間,消除碎片。shrink space真正做到了對段的壓縮,包括初始分配的也壓縮了,所以是hwm上和下的操作。根據需求來選擇壓縮方式。如果以後還會達到以前hwm高度,則選擇move更合適。 

1move可以透過制定storage引數做到真正壓縮分配空間;

2使用move時會改變一些記錄的rowid,所以move後索引會變為無效,需要rebuild

3使用shrink space時,索引會自動維護。如果在業務繁忙時做壓縮,可以先shrink space compact,來壓縮,shrink space cascade會同時壓縮索引。可以用alter index xxx shrink space

4shrink space需要在表空間是自動段空間的,所以system表空間上的表無法shrink space

 

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

相關文章