寫有效的歷史資料遷移sql

2021-08-22 20:11:26 字數 3262 閱讀 3083

**:

對於高併發oltp系統,生產庫可能只需保留當前幾個月的資料,之前的資料要全部遷移到歷史庫中。那麼,如何處理這樣的需求,如何寫合適的歷史遷移程式呢?

1.常規寫法

begin

--遷移資料

insert into tb_users

select *

from tb_users_dbc a

where gmt_modified <= trunc(sysdate) - v_day and rownum<5000000;

--刪除原表資料

delete from tb_users_dbc

where gmt_modified <= trunc(sysdate) - v_day and rownum<5000000;

commit;

end;

2.使用for迴圈

declare

v_counts number := 0;

begin

--中間表

insert into tmp_tb_users

select *

from tb_users_dbc

where gmt_modified <= trunc(sysdate) - v_day and rownum<5000000;

commit;

for i in (select id from tmp_tb_users) loop

--資料遷移

insert into tb_users

select * from tb_users_dbc where id = i.id;

delete from tb_users_dbc where id = i.id;

v_counts := v_counts + 1;

--分批提交

if mod(v_counts, 100) = 0 then

commit;

end if;

end loop;

end;

3.使用bulk collect

declare

type rec_rids is table of varchar2(32);

v_rids rec_rids;

cursor cur_aids is

select id

from tb_users_dbc

where gmt_modified <= trunc(sysdate) - v_day and rownum<5000000;

begin

open cur_aids;

loop

fetch cur_aids bulk collect into v_rids limit 1000;

for i in 1 .. v_rids.count loop

--資料遷移

insert into tb_users

select * from tb_users_dbc where id = v_rids(i);

delete from tb_users_dbc where id = v_rids(i);

end loop;

commit;

exit when v_rids.count = 0;

end loop;

close cur_aids;

end;

很少考慮常規寫法,資料遷移一般會選擇採用2,3種方法。

相比for遷移方式,採用bulk collect避免了上下文切換,在大批量資料遷移中還是有很大優勢的,推薦採用bulk collect資料遷移方案。

asktom上有很多關於歷史遷移方案的帖子,tom的答案一直都是常規寫法,也就是上面的第一種寫法,可是常規寫法消耗大量的資源,出現異常時整個事務都得回滾。因此很多人都認為tom的方案不可行,認為tom並沒有接觸過大資料庫等。

4.借助tom的思想,把遷移的資料拆分成n個小表,對n個小表進行遷移

declare

pagecount number;

sumcount number;

loopcount number;

begin

--取要遷移的資料

execute immediate 'truncate table tmp_tb_users';

insert into tmp_tb_users

select id

from tb_users_dbc

where gmt_modified <= trunc(sysdate) - v_day and rownum < 5000000;

--計算遷移總數

select count(*) into sumcount from tmp_tb_users;

--設定每次遷移條數

pagecount = 2000;

--得到迴圈次數

loopcount := sumcount / pagecount + 1;

for i in 1 .. loopcount loop

begcount := (i - 1) * pagecount + 1;

endcount := i * pagecount;

--構建中間小表

execute immediate 'truncate table mid_tb_users';

insert into mid_tb_users

select id, b.rn

from tmp_tb_users b where b.rn >= begcount and b.rn <= endcount;

--小表和原表進行關聯,遷移資料

insert into tb_users

select f.*

from mid_tb_users t, tb_users_dbc f

where t.biz_order_id = f.biz_order_id

and t.rn >= begcount and t.rn < = endcount;

--刪除原表資料

delete from tb_users_dbc where id in (select id from mid_tb_users);

commit;

end loop;

end;

1.優於常規寫法,可以分批多次進行提交,加入異常處理可以避免全部資料回滾。

2.優於for遷移,借助中間小表一次遷移多條記錄,大大降低了insert,delete的執行次數。

3.主要是提供給大家一種思路。

注:上面指令碼是偽**

寫有效的歷史資料遷移sql

對於高併發oltp系統,生產庫可能只需保留當前幾個月的資料,之前的資料要全部遷移到歷史庫中。那麼,如何處理這樣的需求,如何寫合適的歷史遷移程式呢?1.常規寫法 begin 遷移資料 insert into tb users select from tb users dbc a where gmt m...

對於歷史資料問題的思考

在做企業資訊化的過程中,對於歷史資料和歷史資料包表的處理遇到了些問題,主要是兩個方面 1 歷史資料歸檔。這方面看到了一些討論,主要方向是做乙個相同的歸檔庫,定期將流通資料庫中內容放到歸檔庫或者叫歷史庫中。裡面有幾個細節問題需要考慮怎麼處理 首先是如何描述歸檔規則,也就是如何界定歷史資料 對於不同的資...

寫有效率的SQL查詢(I)

1.1where條件的列上都得有統計資訊。沒統計資訊sqlserver就無法估算不同查詢計畫開銷優劣,而只能採用最穩妥的scan 不管是table scan還是clustered index scan 一般情況下我們不會犯這種錯誤 where條件裡不使用非索引列是個常識。索引上的統計資訊是無法刪除的...