Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          Oracle中的move命令
          ?
          ??? 從8i開始,oracle開始提供Move的命令。我們通常使用這個命令,將一個table segment從一個tablespace移動到另一個tablespace。Move實際上是在block之間物理的copy數據,那么,我們可以通過這種方式來降低table的HWM。我們先通過一個實驗來看看move是如何移動數據的。
          ?
          ?
          1.建表并插入數據:
          ?
          SQL> create table sjh.test1(id int) tablespace users;
          ?
          表已創建。
          ?
          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;
          ??????? ID
          ----------
          ???????? 1
          ???????? 2
          ???????? 3
          ???????? 4
          ???????? 5
          ???????? 6
          ???????? 7
          ???????? 8
          ?
          已選擇8行。
          ?
          ?
          2.查看表的rowid信息和block id信息:
          ?
          SQL> select rowid,id from sjh.test1;
          ?
          ROWID????????????????????? ID
          ------------------ ----------
          AAAMlQAAEAAAABHAAA????????? 1
          AAAMlQAAEAAAABHAAB????????? 2
          AAAMlQAAEAAAABHAAC????????? 3
          AAAMlQAAEAAAABHAAD????????? 4
          AAAMlQAAEAAAABHAAE????????? 5
          AAAMlQAAEAAAABHAAF????????? 6
          AAAMlQAAEAAAABHAAG????????? 7
          AAAMlQAAEAAAABHAAH????????? 8
          ?
          已選擇8行。
          ?
          SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS
          ?2 ? from dba_extents where segment_name='TEST1';
          ?
          EXTENT_ID??? FILE_ID RELATIVE_FNO?? BLOCK_ID???? BLOCKS
          ---------- ---------- ------------ ---------- ----------
          ???????? 0????????? 4??????????? 4???????? 65????????? 8
          ?
          --8條記錄都在一個塊上(AAAABH)
          ?
          這里簡單介紹一下ROWID的知識:ROWID 在磁盤上需要10個字節的存儲空間并使用18個字符來顯示它包含下列組件:
          ?
          數據對象編號:每個數據對象如表或索引在創建時都分配有此編號,并且此編號在數據庫中是唯一的;
          相關文件編號:此編號對于一個表空間中的每個文件是唯一的;
          塊編號:表示包含此行的塊在文件中的位置;
          行編號:標識塊頭中行目錄位置的位置;
          ?
          在內部數據對象編號需要32 位,相關文件編號需要10 位,塊編號需要22,位行編號需要16 位,加起來總共是80 位或10 個字節,ROWID 使用以64 為基數的編碼方案來顯示該方案將六個位置用于數據對象,編號三個位置用于相關文件編號六個位置用于塊編號三個位置用于行編號以64 為基數的編碼方案使用字符A-Z a-z 0-9 + 和/共64 個字符,
          ?
          如下例所示:AAAMlQ AAE AAAABH AAA
          ?
          在本例中
          AAAMlQ ?? 是數據對象編號
          AAE?????? 是相關文件編號
          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????????????????????? ID
          ------------------ ----------
          AAAMlQAAEAAAABHAAB????????? 2
          AAAMlQAAEAAAABHAAD????????? 4
          AAAMlQAAEAAAABHAAF????????? 6
          AAAMlQAAEAAAABHAAG????????? 7
          AAAMlQAAEAAAABHAAH????????? 8
          ?
          --我們看到ROWID保持不變。
          ?
          ?
          4.做MOVE操作,然后觀察ROWID的情況:
          ?
          SQL> alter table sjh.test1 move;
          ?
          表已更改。
          ?
          SQL> select rowid,id from sjh.test1;
          ?
          ROWID????????????????????? ID
          ------------------ ----------
          AAAMlRAAEAAAABMAAA????????? 2
          AAAMlRAAEAAAABMAAB????????? 4
          AAAMlRAAEAAAABMAAC????????? 6
          AAAMlRAAEAAAABMAAD????????? 7
          AAAMlRAAEAAAABMAAE????????? 8
          ?
          SQL> select EXTENT_ID,FILE_ID,RELATIVE_FNO,BLOCK_ID,BLOCKS
          ?2?? from dba_extents where segment_name='TEST1';
          ?
          EXTENT_ID??? FILE_ID RELATIVE_FNO?? BLOCK_ID???? BLOCKS
          ---------- ---------- ------------ ---------- ----------
          ???????? 0????????? 4??????????? 4???????? 73????????? 8
          ?
          --ROWID發生變化BLOCK_ID由原來的65變為73,BLOCK的編號由原來的AAAABH變為AAAABM
          ?
          ?
          5.move對HWM的影響:
          ?
          這里引用網友yjz0065的一個例子:
          ?
          SQL> create table my_objects tablespace HWM
          ?2?? as select * from all_objects;
          ?
          SQL> delete from my_objects where rownum<10000;
          ?
          9999 rows deleted
          ?
          SQL> select count(*) from my_objects;
          ?
          COUNT(*)
          ----------
          ???? 21015
          ?
          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

          然后對table MY_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
          ?
          我們可以看到,table MY_OBJECTS的HWM從423移動到290,table的HWM降低了!(show_space是自定義的一個過程)
          ?
          ?
          ?
          Move的一些用法:
          ?
          以下是alter table 中move子句的完整語法,我們介紹其中的幾點:
          ?
          MOVE [ONLINE]
          [segment_attributes_clause]
          [data_segment_compression]
          [index_org_table_clause]
          [ { LOB_storage_clause | varray_col_properties }
          ??? [ { 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_indexes where index_name='I_MY_OBJECTS';
          ?
          INDEX_NAME???????????????????? STATUS
          ------------------------------ --------
          I_MY_OBJECTS?????????????????? UNUSABLE
          ?
          從這里可以看到,當table MY_OBJECTS進行move操作后,該table 上的inedx的狀態為UNUSABLE,這時,我們可以使用alter index I_MY_OBJECTS rebuild online的命令,對index I_MY_OBJECTS進行在線rebuild。
          ?
          b. move時對table的鎖定
          ?
          當我們對table MY_OBJECTS進行move操作時,查詢v$locked_objects視圖可以發現,table MY_OBJECTS上加了exclusive lock:
          SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;
          ?
          OBJECT_ID SESSION_ID ORACLE_USERNAME??? LOCKED_MODE
          ---------- ---------- ------------------ -----------
          ???? 32471????????? 9 DLINGER????????????????????? 6
          ?
          SQL> select object_id from user_objects where object_name = 'MY_OBJECTS';
          OBJECT_ID
          ----------
          ???? 32471
          ?
          這就意味著,table在進行move操作時,我們只能對它進行select的操作。反過來說,當我們的一個session對table進行DML操作且沒有commit時,在另一個session中是不能對這個table進行move操作的,否則oracle會返回這樣的錯誤信息:ORA-00054: 資源正忙,要求指定 NOWAIT。
          ?
          c. 關于move時空間使用的問題:
          ?
          當我們使用alter table move來降低table的HWM時,有一點是需要注意的,這時,當前的tablespace中需要有1倍于table的空閑空間以供使用:
          ?
          SQL> CREATE TABLESPACE TEST1
          ?2 ? DATAFILE 'D:\ORACLE\ORADATA\ORACLE9I\TEST1.dbf' SIZE 5M
          ?3 ? UNIFORM SIZE 128K ;
          SQL> create table my_objects tablespace test1 as select * from all_objects;
          ?
          表已創建。
          SQL> select bytes/1024/1024 from user_segments where segment_name='MY_OBJECTS';
          ?
          BYTES/1024/1024
          ---------------
          ????????? 3.125
          ?
          SQL> alter table MY_OBJECTS move;
          alter table MY_OBJECTS move
          ??????????? *
          ERROR 位于第 1 行:
          ?
          ORA-01652: 無法通過16(在表空間TEST1中)擴展 temp 段
          SQL> ALTER DATABASE
          ?2? DATAFILE 'D:\ORACLE\ORADATA\ORACLE9I\TEST1.DBF' RESIZE 7M;
          數據庫已更改。
          SQL> alter table MY_OBJECTS move;
          表已更改。
          ?
          posted on 2009-07-13 21:49 decode360 閱讀(2567) 評論(0)  編輯  收藏 所屬分類: 07.Oracle
          主站蜘蛛池模板: 安顺市| 东乌珠穆沁旗| 怀柔区| 镇坪县| 江油市| 虎林市| 大姚县| 江源县| 监利县| 汶川县| 德令哈市| 青铜峡市| 定南县| 广元市| 安西县| 彰化市| 凌源市| 根河市| 扬州市| 达尔| 广西| 平乐县| 克什克腾旗| 西丰县| 玛沁县| 榕江县| 上饶县| 丰镇市| 江孜县| 定陶县| 宜川县| 松溪县| 和硕县| 盘锦市| 荥经县| 阿荣旗| 淮北市| 龙游县| 和平县| 泰顺县| 绥化市|