Oracle中shrink space命令

shrink_clause:sql

  http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_3001.htm#i2192484
 

首先oracle shrink 是10g以後才引出的,有shrink table 和shrink space兩種,這裏介紹shrink space數據庫

壓縮分兩個階段:oracle

一、數據重組:這個過程是經過一系列的insert delete操做,將數據儘可能排在列的前面進行從新組合。函數

二、HWM調整:這個過程是對HWM的調整,釋放空閒數據庫。post

PS:shrink之間必須開啓行移動功能性能

alter table table_name enable row movement;ui

基本語法:spa

alter table <table_name> shrink space [ <null> | cascade | compact  ];.net

--alter table <table_name> shrink space compact;日誌

只收縮表,這個其實是隻執行了第一個階段,HWM保持不變。

--alter table <table_name>  shrink space cascade;

收縮表而且相關索引也會被收縮,HWM會下降

--alter table <table_name> shrink space;

收縮表,下降HWM(High Water Mark)

 

 

限制條件:
一、不能對cluster、clustered  table 或者任何有LONG列的對象使用這個語句
二、壓縮段不支持有函數索引、位圖連接索引的表
三、這語句不能壓縮二級索引表的映射表,即便設置了CASCADE
四、不能對壓縮表使用該語句
五、不能壓縮on commit 類型的物化視圖的主表,rowid物化視圖必須在壓縮操做以後重建
 
詳解:
oracle10g開始提供shrink的命令,要求表空間是自動段空間管理(ASSM),下降HWM。
 
segment shrink 分爲兩個階段:
 
一、數據重組(compact):經過一系列insert、delete操做,將數據儘可能排在段的前面,這個過程當中須要在表上加RX鎖,及只須要移動的行上加鎖。因爲涉及到rowid的改變,須要enable row movement。同時要distable基於rowid的triggers,這個過程對業務影響比較小(--因爲採用compact,只有涉及移動的行才加鎖,因此不會鎖定整個表,其餘的DML操做有部分能夠進行,進而減少系統高峯期的性能開銷)
 
二、HWM調整:第二階段是調整HWM位置,釋放空閒數據塊,此過程須要在表上加X鎖(獨享鎖,所以這個表都被鎖定,若是系統處在高峯期的時候,其餘在此表的DML被掛起,會產生嚴重阻塞),會形成表上全部DML語句阻塞,系統忙時影響較大,
 
  • shrink space語句兩個階段都執行
  • shrink space compact語句只執行第一個階段。
  • 在業務繁忙的時候,能夠先執行shrink space compact重組數據,而後不滿的時候執行shrink space下降HWM釋放空閒數據塊。
  • shrink必須開啓對象的row movement功能(shrink index 不須要),alter table table_name enable row movement.可是要注意,該語句會形成引用table_name的對象(如存儲過程、包、試圖等)變爲無效,執行完最好由utlrp.sql來編譯無效對象。
  • shrink不會使表的索引失效。可是move會,所以,move後必須重建索引,(alter table table_name move;alter index index_name rebuild)
 
語法:
alter table shrink space[|cpmpact|cascade];
alter table shrink space compcat; 把塊中的數據堆到一塊兒,但會保持high water mark
alter table shrink space;收縮表,下降high water mark
alter table shrink space cascade;收縮表,下降high water mark,並相關索引也要收縮。
alter index indexname shrink space;收縮索引

補充:
--編譯無效對象腳本utlrp.sql 

  >$ sqlplus /no log
    SQL>connect sys/pwd@sid AS sysdba
    SQL>@?/rdbms/admin/utlrp.sql 

  utlrp.sql腳本能夠在數據庫運行的狀態下執行以編譯、數據庫中的invalid對象. 
  oracle建議在對數據庫進行遷移、升級、降級後都運行一遍utlrp.sql以編譯無效對象。 

--打完patch後重建數據字典視圖腳本catpatch.sql 

  爲了保證系統的的數據詞典的完整性和有效性,最好的打patch後在migrate狀態下運行catpatch.sql 
  sql> shutdown immediate 
  sql> startup migrate 
  sql> @?/rdbms/admin/catpatch.sql 
  sql> shutdown immediate 
  sql> startup 

  爲加快速度,可臨時調大這2個參數: 
  show parameter shared_pool_size 
  show parameter large_pool_size 
 

1.1 建立ASSM的表空間

SQL> set serveroutput on

SQL> create tablespace ASSM datafile '/oradata/ltest/assm.dbf' size 10m autoextend on SEGMENT SPACE MANAGEMENT AUTO;

Tablespace created

SQL> select tablespace_name,

  2         block_size,

  3         extent_management,

  4         allocation_type,

  5         segment_space_management

  6    from dba_tablespaces

  7   where tablespace_name = 'ASSM';

 

TABLESPACE_NAME BLOCK_SIZE EXTENT_MANAGEMENT ALLOCATION_TYPE SEGMENT_SPACE_MANAGEMENT

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

ASSM                  8192 LOCAL             SYSTEM          AUTO

1.2 建表

SQL> create table my_objects tablespace assm as select * from all_objects;

Table created

SQL> select count(*) from my_objects;

  COUNT(*)

----------

     49903

2 實驗前的信息

SQL> exec show_space('MY_OBJECTS');

 

Total Blocks  ..........................768

Total Bytes   ..........................6291456

Total MBytes  ..........................6

Unused Blocks ..........................62

Unused Bytes  ..........................507904

Unused KBytes ..........................496

Last Used Ext FileId....................7

Last Used Ext BlockId...................649

Last Used Block.........................66

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................0

FS3 Blocks (50-75)  ....................0

FS4 Blocks (75-100) ....................0

Unformatted Blocks  ....................0

Full Blocks         ....................686

 

PL/SQL procedure successfully completed

3 刪除後的信息

而後咱們隨機地從table MY_OBJECTS中刪除一部分數據:

 

SQL> delete from my_objects where object_name like '%C%';

17674 rows deleted

SQL> delete from my_objects where object_name like '%U%';

4687 rows deleted

SQL> delete from my_objects where object_name like '%A%';

7010 rows deleted

 

SQL> exec show_space('MY_OBJECTS');

 

Total Blocks  ..........................768

Total Bytes   ..........................6291456

Total MBytes  ..........................6

Unused Blocks ..........................62

Unused Bytes  ..........................507904

Unused KBytes ..........................496

Last Used Ext FileId....................7

Last Used Ext BlockId...................649

Last Used Block.........................66

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................212

FS3 Blocks (50-75)  ....................181

FS4 Blocks (75-100) ....................245

Unformatted Blocks  ....................0

Full Blocks         ....................48

 

PL/SQL procedure successfully completed

 

這裏,table my_objects的HWM下有706(768 - 62)個block,其中,free space爲25-50%的block有205個,free space爲50-75%的block有180個,free space爲75-100%的block有229個,full space的block只有45個,這種狀況下,咱們須要對這個table的現有數據行進行重組。

4 shink操做

要使用assm上的shink,首先咱們須要使該表支持行移動,能夠用這樣的命令來完成:

SQL> alter table my_objects enable row movement;

Table altered

如今,就能夠來下降my_objects的HWM,回收空間了,使用命令:

SQL> alter table my_objects shrink space;

Table altered

 

SQL> exec show_space('MY_OBJECTS');

Total Blocks  ..........................280

Total Bytes   ..........................2293760

Total MBytes  ..........................2.1875

Unused Blocks ..........................5

Unused Bytes  ..........................40960

Unused KBytes ..........................40

Last Used Ext FileId....................7

Last Used Ext BlockId...................265

Last Used Block.........................19

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................1

FS3 Blocks (50-75)  ....................1

FS4 Blocks (75-100) ....................0

Unformatted Blocks  ....................0

Full Blocks         ....................259

 

PL/SQL procedure successfully completed

 

在執行玩shrink命令後,此時表my_objects的HWM如今降到了276(280 - 5 + 1)的位置,並且HWM下的block的空間使用情況,full space的block有259個,free space 爲25-50% 和50-75% Block只有1個。

5 shrink space原理剖析

5.1 實驗環境

SQL> create table TEST_HWM (id int ,name char(2000)) tablespace ASSM;

Table created

SQL> insert into TEST_HWM values (1, 'aa');

1 row inserted

SQL> insert into TEST_HWM values (2, 'bb');

1 row inserted

SQL> insert into TEST_HWM values (3, 'cc');

1 row inserted

SQL> insert into TEST_HWM values (4, 'ds');

1 row inserted

SQL> insert into TEST_HWM values (5, 'dss');

1 row inserted

SQL> insert into TEST_HWM values (6, 'dss');

1 row inserted

SQL> insert into TEST_HWM values (7, 'ess');

1 row inserted

SQL> insert into TEST_HWM values (8, 'es');

1 row inserted

SQL> insert into TEST_HWM values (9, 'es');

1 row inserted

SQL> insert into TEST_HWM values (10, 'es');

1 row inserted

5.2 刪除前rowid狀態

SQL> select id,

  2         name,

  3         rowid,

  4         dbms_rowid.rowid_object(rowid) object_id,

  5         dbms_rowid.rowid_relative_fno(rowid) file_id,

  6         dbms_rowid.rowid_block_number(rowid) block_id,

  7         dbms_rowid.rowid_row_number(rowid) num

  8    from test_hwm;

 

    ID NAME  ROWID               OBJECT_ID    FILE_ID   BLOCK_ID        NUM

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

     1 aa    AAANAqAAHAAAAElAAA      53290          7        293          0

     2 bb    AAANAqAAHAAAAElAAB      53290          7        293          1

     3 cc    AAANAqAAHAAAAElAAC      53290          7        293          2

     4 ds    AAANAqAAHAAAAEmAAA      53290          7        294          0

     5 dss   AAANAqAAHAAAAEmAAB      53290          7        294          1

     6 dss   AAANAqAAHAAAAEmAAC      53290          7        294          2

     7 ess   AAANAqAAHAAAAEnAAA      53290          7        295          0

     8 es    AAANAqAAHAAAAEnAAB      53290          7        295          1

     9 es    AAANAqAAHAAAAEnAAC      53290          7        295          2

    10 es    AAANAqAAHAAAAEoAAA      53290          7        296          0

10 rows selected

5.3 刪除後rowid狀態

而後從table test_hwm中刪除一些數據:

SQL> delete from TEST_HWM where id = 2;

1 row deleted

SQL> delete from TEST_HWM where id = 3;

1 row deleted

SQL> delete from TEST_HWM where id = 4;

1 row deleted

SQL> delete from TEST_HWM where id = 7;

1 row deleted

SQL> delete from TEST_HWM where id = 8;

1 row deleted

 

SQL> select id,

  2         name,

  3         rowid,

  4         dbms_rowid.rowid_object(rowid) object_id,

  5         dbms_rowid.rowid_relative_fno(rowid) file_id,

  6         dbms_rowid.rowid_block_number(rowid) block_id,

  7         dbms_rowid.rowid_row_number(rowid) num

  8    from test_hwm;

 

    ID NAME  ROWID               OBJECT_ID    FILE_ID   BLOCK_ID        NUM

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

     1 aa    AAANAqAAHAAAAElAAA      53290          7        293          0

     5 dss   AAANAqAAHAAAAEmAAB      53290          7        294          1

     6 dss   AAANAqAAHAAAAEmAAC      53290          7        294          2

     9 es    AAANAqAAHAAAAEnAAC      53290          7        295          2

    10 es    AAANAqAAHAAAAEoAAA      53290          7        296          0

 

從以上的信息,可知表test_hwm中,剩下的數據是分佈在AAAAEl,AAAAEm,AAAAEn,AAAAEo這樣四個連續的block中。

 

SQL> exec show_space('TEST_HWM');

Total Blocks  ..........................8

Total Bytes   ..........................65536

Total MBytes  ..........................0.0625

Unused Blocks ..........................0

Unused Bytes  ..........................0

Unused KBytes ..........................0

Last Used Ext FileId....................7

Last Used Ext BlockId...................289

Last Used Block.........................8

 

The segment is analyzed below

FS1 Blocks (0-25)   ....................0

FS2 Blocks (25-50)  ....................1

FS3 Blocks (50-75)  ....................3

FS4 Blocks (75-100) ....................1

Unformatted Blocks  ....................0

Full Blocks         ....................0

 

PL/SQL procedure successfully completed

 

經過show_space_assm咱們能夠看到目前這四個block的空間使用情況,AAAAEl,AAAAEn,AAAAEo上各有一行數據,能夠猜想free space爲50-75%的3個block是這三個block,那麼free space爲25-50%的1個block就是AAAAEm了,剩下free space爲 75-100% 的3個block,是HWM下已格式化的還沒有使用的block。

5.4 shrink後rowid狀態

SQL> alter table my_objects enable row movement;

Table altered

SQL> alter table my_objects shrink space;

Table altered

 

SQL> select id,

  2         name,

  3         rowid,

  4         dbms_rowid.rowid_object(rowid) object_id,

  5         dbms_rowid.rowid_relative_fno(rowid) file_id,

  6         dbms_rowid.rowid_block_number(rowid) block_id,

  7         dbms_rowid.rowid_row_number(rowid) num

  8    from test_hwm;

 

    ID NAME  ROWID               OBJECT_ID    FILE_ID   BLOCK_ID        NUM

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

     9 es    AAANAqAAHAAAAEkAAA      53290          7        292          0

    10 es    AAANAqAAHAAAAEkAAB      53290          7        292          1

     1 aa    AAANAqAAHAAAAElAAA      53290          7        293          0

     5 dss   AAANAqAAHAAAAEmAAB      53290          7        294          1

     6 dss   AAANAqAAHAAAAEmAAC      53290          7        294          2

 

當執行了shrink操做後,能夠發現shrink操做與move不太同樣。在move操做的時候,全部行的rowid都發生了變化,table所位於的block的區域也發生了變化,可是全部行物理存儲的順序都沒有發生變化,因此咱們獲得的結論是,oracle以block爲單位,進行了block間的數據copy。而在shrink後,部分行數據的rowid發生了變化,同時,部分行數據的物理存儲的順序也發生了變化,而table所位於的block的區域卻沒有變化(ID爲1,5,6的rowid沒有發生變化,ID爲9,10兩行數據,原來在AAAAEn,AAAAEo上都移到AAAAEk上)。以上說明,shrink只移動了table其中一部分的行數據,來完成釋放空間,並且,這個過程是在table當前所使用的block中完成的。

6 shrink的注意點

1. move時產生的日誌比shrink時少.參看http://blog.csdn.net/huang_xw/article/details/7016365

2. shrink在移動行數據時,也一塊兒維護了index上相應行的數據rowid的信息,固然shrink過程當中用來維護index的成本也會比較高。而表move後index的狀態是UNUSABLE的,須要進行rebuild。參見http://blog.csdn.net/huang_xw/article/details/7016415

3. oracle是從後向前移動行數據,那麼,shrink的操做就不會像move同樣,shrink不須要使用額外的空閒空間。

相關文章
相關標籤/搜索