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不須要使用額外的空閒空間。