享受生活,享受工作,做个快乐的自己! - Dreams are always dreams when you don't even take a try!
查看文章 |
对大表的快速复制
2009年08月27日 星期四 14:56
一般我们采用复制表的方式主要是 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-- |
最近读者:

