(轉)oracle資料庫之間 表複製方法一(extent 方法)

mahanso發表於2011-05-25
一般我們採用複製表的方式主要是
create table table_name
as select /*+ parallel (t 10)*/ * from t_name t ...

insert /*+ append */ into table_name
select /*+ parallel (t 10)*/ * from tname t ... 

這兩者方法都沒有問題,但如果資料量到達一定程度,比如說10億,大小400G,而且表上還存在業務,這樣的話,很容易出現01555的問題。 我在執行了3個小時後遇到了惱人的01555,將undo_retention改到一個足夠大的值還是不行,畢竟表太大,而且表上有業務在更新資料。

有一種方式可以避免01555,可以從物理備庫恢復到某個時刻後,從備庫表拖資料,這樣上面的問題是沒有了,不過有一點是需要考慮的,透過單dblink的話是有網路流量限制的,一般是20M/S,這樣400G的表需要7個小時,還是太慢了。 

最終考慮採用extent的方式,一塊一塊的拖,在我預想這樣的速度應該會比直接在主庫複製一個新表要慢一下的。
事實勝於雄辯,採用extent的方式,開12個程式,花了2個半小時完成了整個表的複製。不開12個並行直接複製錶快了30%,而且採用extnt的方式比較靈活,可以在很多情況下繼續上次為完成的工作,就是所謂的斷點了,當然這種方式也是有一定代價的,負載會比前面的方法至少高一倍以上 

------------------------------------------------------------
create table MY_ROWID
(
ID        NUMBER,
ROWID_MIN VARCHAR2(100),
ROWID_MAX VARCHAR2(100),
HAS_DEAL NUMBER
);


insert into my_rowid(id,rowid_min,rowid_max,has_deal)
select rownum,
DBMS_ROWID.ROWID_CREATE(1,o.data_object_id,e.RELATIVE_FNO,e.BLOCK_ID,0),
DBMS_ROWID.ROWID_CREATE(1,o.data_object_id,e.RELATIVE_FNO,e.BLOCK_ID+e.BLOCKS-1,10000),
0
from dba_extents e,dba_objects o
where e.segment_name=upper('base_table')
and e.owner='FBADMIN'
AND o.object_name = upper('base_table')
AND o.owner='FBADMIN';

commit;
----------------------------------------------------------------------
CREATE OR REPLACE PROCEDURE SP_XF_COPY_TABLE(N NUMBER) IS
/* 
複製評價表
2009-8-26
*/

V_SQLERRM VARCHAR2(200);
BEGIN
FOR C IN (SELECT ID, ROWID_MIN, ROWID_MAX
FROM MY_ROWID
WHERE HAS_DEAL = 0
AND MOD(ID, 12) = N) LOOP

INSERT INTO      
SELECT /*+ rowid(t) */
*
FROM base_table t
WHERE ROWID >= CHARTOROWID(C.ROWID_MIN)
AND ROWID <= CHARTOROWID(C.ROWID_MAX);

UPDATE MY_ROWID SET HAS_DEAL = 1 WHERE ID = C.ID;
COMMIT;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
V_SQLERRM := SUBSTR(SQLERRM, 1, 200);
DBMS_OUTPUT.PUT_LINE(V_SQLERRM);

ROLLBACK;
END SP_XF_COPY_TABLE;

---------

儘量使用後臺跑指令碼
nohup $HOME/worksh/sp_xf_tmp00.sh >/tmp/sp_xf_tmp00.txt &

--check data
SELECT COUNT(*) from my_rowid t WHERE has_deal = 0;


~~~~~~~~~~~~~~~~~~~~~
很多情況下可以使用extent來處理大表的資料

--EOF--
insert /*+APPEND */into mytable(select 列名,列名,...... from i_mytable);這樣估計要快很多

如果需要更快 

需要用PLSQL

declare

i number(10);

begin

insert /*+APPEND */into mytable(select 列名,列名,...... from i_mytable);

i:=sql%rowcount;

if i%1000=0 then

commit;

end if;

end;

強制批次插入  並且 不要在大表使用*函式  是SQL最佳化的關鍵

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

相關文章