批量更新總結
最近遇到一個這麼一個業務:每晚根據另一個系統上報的資料(表 t_taemployee ,100W左右資料),更新正式系統裡面對應名單(表tatable, 2000W左右資料)的狀態等資訊,基於商業原因,這裡的表名及欄位名都已做處理,分別採用別名代替.
實現方式:定義一個procedure,採用Job來定時呼叫procedure執行,其procedure程式碼(已處理過)如下
create or replace procedure upload_state as
curyear number;
curmonth number;
tatable varchar(100) := 't_test1_';
fetable varchar(100) := 't_test2_';
cout number := 0;
rowindex number := 0;
exc_time exception;
exc_ta exception;
exc_fe exception;
insert_err varchar(200) := 'insert into t_synerror2(message) values(:message)';
type v_cursor is ref cursor;
y_cursor v_cursor;
f_cursor v_cursor;
query_y varchar2(1000);
query_f varchar2(1000);
type y_rec is record(
state number,
sje number,
row_id varchar2(20));
type f_rec is record(
state number,
row_id varchar2(20));
type y_array_type is table of y_rec;
type f_array_type is table of f_rec;
y_array y_array_type;
f_array f_array_type;
begin
select count(1)
into cout
from user_tables
where table_name = upper('t_synerror2');
if cout = 0 then
execute immediate 'create table t_synerror2(
notedate date default sysdate,
message varchar(100))';
end if;
select extract(year from(sysdate - 1)), extract(month from(sysdate - 1))
into curyear, curmonth
from dual;
if curmonth = 2 or curmonth = 8 then
raise exc_time;
end if;
tatable := tatable || curyear || curmonth;
select count(1)
into cout
from user_tables
where table_name = upper(tatable);
if cout = 0 then
raise exc_ta;
end if;
fetable := fetable || curyear || curmonth;
select count(1)
into cout
from user_tables
where table_name = upper(fetable);
if cout = 0 then
raise exc_fe;
end if;
--bluck collect
--
query_y := 'select ad.state, ad.sje, y.rowid row_id
from st_goup sj, t_taemployee ad, ' ||
tatable || ' y
where sj.js_id = ad.sid
and sj.state = 1
and sj.q_id = y.sid';
open y_cursor for query_y;
fetch y_cursor bulk collect
into y_array;
close y_cursor;
for r in y_array.first .. y_array.last loop
execute immediate 'update ' || tatable ||
' y set y.state = :state, y.sje = :sje where rowid=:rowd'
using y_array(r).state, y_array(r).sje, y_array(r).row_id;
rowindex := rowindex + 1;
if rowindex = 1000 then
rowindex := 0;
commit;
end if;
end loop;
commit;
/*
execute immediate '
update ' || tatable || ' y
set y.state = (select ad.state
from st_goup sj, t_taemployee ad
where sj.js_id = ad.sid
and sj.state = 1
and q_id = y.sid),
y.sje = (select ad.sje
from st_goup sj, t_taemployee ad
where sj.js_id = ad.sid
and sj.state = 1
and q_id = y.sid)
where exists (select sj.q_id
from st_goup sj, t_taemployee ad
where sj.js_id = ad.sid
and sj.state = 1
and q_id = y.sid)';
commit;
*/
--bluck collect
--
query_f := 'select fe.state, ff.rowid
from st_goup sj,
t_femployee fe,
' || fetable || ' ff
where sj.js_id = fe.sid
and sj.state = 1
and q_id = ff.sid';
open f_cursor for query_f;
fetch f_cursor bulk collect
into f_array;
close f_cursor;
rowindex := 0;
for r in f_array.first .. f_array.last loop
execute immediate 'update ' || fetable || ' f
set f.state = :state where rowid = :row_id'
using f_array(r).state, f_array(r).row_id;
rowindex := rowindex + 1;
if rowindex = 1000 then
rowindex := 0;
commit;
end if;
end loop;
commit;
/*
execute immediate '
update ' || fetable || ' f
set f.state = (select fe.state
from st_goup sj, t_femployee fe
where sj.js_id = fe.sid
and sj.state = 1
and q_id = f.sid)
where exists (select sj.q_id
from st_goup sj, t_femployee fe
where sj.js_id = fe.sid
and sj.state = 1
and q_id = f.sid)';
commit;
*/
exception
when exc_time then
execute immediate insert_err
using '當前系統月份為“' || curmonth || '”,...';
commit;
when exc_ta then
execute immediate insert_err
using '當前系統年月(' || curyear || ',' || curmonth || ')...“' || tatable || '”還未生成';
commit;
when exc_fe then
execute immediate insert_err
using '當前系統年月(' || curyear || ',' || curmonth || ')...“' || fetable || '”還未生成';
commit;
end upload_state;
/
以上是使用bulk collect into優化後的效果,該指令碼通過job呼叫,一分鐘左右執行完成.
而優化前,沒有用到bulk collect into ,而是直接update(註釋掉的指令碼),執行了近5小時,最後不得不手動停止Job執行.
這裡僅僅提供給大家一個批量更新的參考,不做過多說明.
cursor md_20113 is
select /*+parallel(y1,10) parallel(y3,10)+*/
y3.rowid
from pub_md_20111 y1, pub_md_20113 y3
where y1.student_id = y3.student_id
and y1.state = y3.state
and y1.state = 3;
type md_rec is table of varchar2(20);
row_id md_rec;
begin
open md_20113;
loop
fetch md_20113 bulk collect
into row_id limit 10000;
forall i in row_id.first .. row_id.last execute immediate
'update pub_md_20113 set state = 0 where rowid=:rid'
using row_id(i)
;
commit;
exit when md_20113%notfound;
end loop;
close md_20113;
end;
/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-686557/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQLServer批量更新SQLServer
- Laravel 批量更新Laravel
- 關於 iOS 批量打包的總結iOS
- 批量更新的陷阱?
- android Ant 批量多渠道打包 總結!Android
- 最新swift 4.0 更新總結Swift
- 數論總結——更新ing
- 移動端總結(更新)
- mysql根據查詢結果批量更新多條資料(插入或更新)MySql
- 如何批量更新資料
- pymysql批量更新資料MySql
- 資料庫-批量更新資料庫
- 批量更新效能比較
- 【持續部署】批量部署工具,總結、對比
- Kendo UI Grid 批量編輯使用總結UI
- 陣列總結,持續更新~陣列
- 【持續更新】重要FLIP總結
- SQL Server修改表結構後批量更新所有檢視SQLServer
- oracle批量新增更新資料Oracle
- Mybatis批量更新三種方式MyBatis
- iOS FMDB 查詢 批量更新iOS
- 一句sql,批量更新SQL
- win系統下git程式碼批量克隆,批量更新Git
- const特性總結(不斷更新)
- PHP 詳細面試總結 (每日更新)PHP面試
- 前端面試題總結(定期更新)前端面試題
- 前端佈局總結(持續更新)前端
- javaScript 習題總結(持續更新)JavaScript
- TSM 6.X版更新總結
- iterator標籤總結(不斷更新)
- iOS 脈絡圖總結匯總 連續更新iOS
- 使用sqlplus批量執行指令碼的總結SQL指令碼
- MySQL批量更新死鎖案例分析MySql
- hibernateHQl批量插入、刪除、更新
- Oracle -- 批量更新sequence的儲存Oracle
- 海量資料處理_批量更新
- 前端面試題總結(陸續更新.......)前端面試題
- electron打包更新與整合sqlite小總結SQLite