Oracle Move命令總結
從8i開始,oracle開始提供Move的命令。我們通常使用這個命令,將一個table segment從一個tablespace移動到另一個tablespace。Move實際上是在block之間物理的copy數據,那麼,我們可以通過這種方式來降低table的HWM。我們先通過一個實驗來看看move是如何移動數據的。
1.建表並插入數據:
SQL> create table sjh.test1(id int) tablespaceusers;
表已創建。
SQL> insert into sjh.test1 values(1);
已創建 1 行。
SQL> insert into sjh.test1 values(2);
已創建 1 行。
SQL> insert into sjh.test1 values(3);
已創建 1 行。
SQL> insert into sjh.test1 values(4);
已創建 1 行。
SQL> insert into sjh.test1 values(5);
已創建 1 行。
SQL> insert into sjh.test1 values(6);
已創建 1 行。
SQL> insert into sjh.test1 values(7);
已創建 1 行。
SQL> insert into sjh.test1 values(8);
已創建 1 行。
S QL> commit;
提交完成。
SQL> select * from sjh.test1;
已選擇8行。
2.查看表的rowid信息和block id信息:
SQL> select rowid,id from sjh.test1;
已選擇8行。
SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS
--8條記錄都在一個塊上(AAAABH)
這裡簡單介紹一下ROWID的知識:ROWID在磁盤上需要10個字節的存儲空間並使用18個字符來顯示它包含下列組件:
數據對象編號:每個數據對象如表或索引在創建時都分配有此編號,並且此編號在數據庫中是唯一的;
相關文件編號:此編號對於一個表空間中的每個文件是唯一的;
塊編號:表示包含此行的塊在文件中的位置;
行編號:標識塊頭中行目錄位置的位置;
在內部數據對象編號需要32 位,相關文件編號需要10 位,塊編號需要22,位行編號需要16 位,加起來總共是80 位或10 個字節,ROWID使用以64 為基數的編碼方案來顯示該方案將六個位置用於數據對象,編號三個位置用於相關文件編號六個位置用於塊編號三個位置用於行編號以64 為基數的編碼方案使用字符A-Z a-z 0-9 + 和/共64 個字符,
如下例所示:AAAMlQAAE AAAABH AAA
3.做一些DML操作,再觀察ROWID有沒有發生變化:
SQL> delete from sjh.test1 where id=1;
已刪除 1 行。
SQL> delete from sjh.test1 where id=3;
已刪除 1 行。
SQL> delete from sjh.test1 where id=5;
已刪除 1 行。
SQL> commit;
提交完成。
SQL> select rowid,id from sjh.test1;
--我們看到ROWID保持不變。
4.做MOVE操作,然後觀察ROWID的情況:
SQL> alter table sjh.test1 move;
表已更改。
SQL> select rowid,id from sjh.test1;
--ROWID發生變化BLOCK_ID由原來的65變為73,BLOCK的編號由原來的AAAABH變為AAAABM
5.move對HWM的影響:
這裡引用網友yjz0065的一個例子:
SQL> create table my_objects tablespace HWM
SQL> delete from my_objects where rownum<10000;
9999 rows deleted
SQL> select count(*) from my_objects;
COUNT(*)
----------
SQL> exec show_space(p_segname =>'MY_OBJECTS',p_owner => 'DLINGER',p_type => 'TABLE');
Total Blocks............................425
Total Bytes.............................3481600
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................11
Last Used Ext BlockId...................1294
Last Used Block.........................2
這裡HWM=425- 3 + 1 = 423
然後對tableMY_OBJECTS進行move操作:
SQL> alter table MY_OBJECTS move;
表已更改。
SQL> exec show_space(p_segname =>'MY_OBJECTS',p_owner => 'DLINGER',p_type => 'TABLE');
Total Blocks............................290
Total Bytes.............................2375680
Unused Blocks...........................1
Unused Bytes............................8192
Last Used Ext FileId....................11
Last Used Ext BlockId...................1584
Last Used Block.........................4
我們可以看到,tableMY_OBJECTS的HWM從423移動到290,table的HWM降低了!(show_space是自定義的一個過程)。
Move的一些用法:
以下是altertable 中move子句的完整語法,我們介紹其中的幾點:
MOVE [ONLINE]
[segment_attributes_clause]
[data_segment_compression]
[index_org_table_clause]
[ { LOB_storage_clause | varray_col_properties }
?0?2?0?2?0?2 [ { LOB_storage_clause | varray_col_properties } ]...
]
[parallel_clause]
a. 我們可以使用move將一個table從當前的tablespace上移動到另一個tablespace上,如:
alter table t move tablespace tablespace_name;
b. 我們還可以用move來改變table已有的block的存儲參數,如:
alter table t move storage (initial 30k next 50k);
c.另外,move操作也可以用來解決table中的行遷移的問題。
使用move的一些注意事項:
a. table上的index需要rebuild:
在前面我們討論過,move操作後,數據的rowid發生了改變,我們知道,index是通過rowid來fetch數據行的,所以,table上的index是必須要rebuild的。
SQL> create index i_my_objects on my_objects (object_id);
Index created
SQL> alter table my_objects move;
Table altered
SQL> select index_name,status from user_indexeswhere index_name='I_MY_OBJECTS';
從這裡可以看到,當tableMY_OBJECTS進行move操作後,該table上的inedx的狀態為UNUSABLE,這時,我們可以使用alterindex I_MY_OBJECTS rebuild online的命令,對index I_MY_OBJECTS進行在線rebuild。
b. move時對table的鎖定
當我們對tableMY_OBJECTS進行move操作時,查詢v$locked_objects視圖可以發現,tableMY_OBJECTS上加了exclusivelock:
SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;
SQL> select object_id from user_objects whereobject_name = 'MY_OBJECTS';
OBJECT_ID
----------
這就意味著,table在進行move操作時,我們只能對它進行select的操作。反過來說,當我們的一個session對table進行DML操作且沒有commit時,在另一個session中是不能對這個table進行move操作的,否則oracle會返回這樣的錯誤信息:ORA-00054: 資源正忙,要求指定 NOWAIT。
c. 關於move時空間使用的問題:
當我們使用altertable move來降低table的HWM時,有一點是需要注意的,這時,當前的tablespace中需要有1倍於table的空閒空間以供使用:
SQL> CREATE TABLESPACE TEST1 DATAFILE 'D:ORACLEORADATAORACLE9ITEST1.dbf' SIZE 5M UNIFORMSIZE 128K ;
SQL> create table my_objects tablespace test1 asselect * from all_objects;
表已創建。
SQL> select bytes/1024/1024 from user_segmentswhere segment_name='MY_OBJECTS';
BYTES/1024/1024
---------------
SQL> alter table MY_OBJECTS move;
alter table MY_OBJECTS move
ERROR 位於第 1 行:
ORA-01652: 無法通過16(在表空間TEST1中)擴展 temp 段
SQL> ALTER DATABASE DATAFILE 'D:ORACLEORADATAORACLE9ITEST1.DBF' RESIZE7M;
數據庫已更改。
SQL> alter table MY_OBJECTS move;
表已更改。