有一个存储过程专门用来从另外一个数据结果表(tab_result)中提取记录并插入到记录详细表(tab_detail)中,如果原来的记录已存在tab_detail中,则更新该记录.
举例说明:
数据结果表tab_result记录如下:
create tab_result
( sn number,--自动增长的数值
callid number, -- callid可能有重复的记录
tdata number(12),
xdata varchar2(10)
);
alter table tab_result add index idx_result on (sn);sn callid tdata xdata
-----------------------------
1 101 223 xxxs
2 232 232 sdfd
3 351 323 232x
4 101 343 3dfdf记录详细表(tab_detail)结构如下:
create table tab_detail
( callid number, --来源于tab_result中的callid
sdata1 number(12),-- sdata1 = tab_result.tdata+tab_result.callid
sdata2 number(12),--sdata2 = tab_result.tdata * 100 +tab_result.callid
xxdata varchar2(10) --xxdata = tab_result.xdata+tab_result.tdata
);
alter table tab_detail add index idx_callid on tab_detail(callid);现在tab_result中有1000W条记录,需要根据一些变换后插入或更新到tab_detail中去.
目前我是用一个大的循环来实现的,循环里面用游标来获取每一行数据再判断tab_detail中时候已存在callid的记录,不存在,则直接插入;已存在则更新到该条callid记录中.但是执行的效率太低,每秒生成100条左右的tab_detail记录.大家帮忙看看有没有好的办法可以优化一下,提高Insert和Update的性能??
举例说明:
数据结果表tab_result记录如下:
create tab_result
( sn number,--自动增长的数值
callid number, -- callid可能有重复的记录
tdata number(12),
xdata varchar2(10)
);
alter table tab_result add index idx_result on (sn);sn callid tdata xdata
-----------------------------
1 101 223 xxxs
2 232 232 sdfd
3 351 323 232x
4 101 343 3dfdf记录详细表(tab_detail)结构如下:
create table tab_detail
( callid number, --来源于tab_result中的callid
sdata1 number(12),-- sdata1 = tab_result.tdata+tab_result.callid
sdata2 number(12),--sdata2 = tab_result.tdata * 100 +tab_result.callid
xxdata varchar2(10) --xxdata = tab_result.xdata+tab_result.tdata
);
alter table tab_detail add index idx_callid on tab_detail(callid);现在tab_result中有1000W条记录,需要根据一些变换后插入或更新到tab_detail中去.
目前我是用一个大的循环来实现的,循环里面用游标来获取每一行数据再判断tab_detail中时候已存在callid的记录,不存在,则直接插入;已存在则更新到该条callid记录中.但是执行的效率太低,每秒生成100条左右的tab_detail记录.大家帮忙看看有没有好的办法可以优化一下,提高Insert和Update的性能??
解决方案 »
- oracle游标使用在where中
- proc的makefile生成的临时文件如何清理
- Oracle CodeSmith代码生成
- 日期查询格式
- dba_users的基表是什么
- OLE DB可以调用ORACLE下返回游标的函数吗?
- 关于ORACLE中单个表分段的问题
- 如何更改oracle 8.1.7.0.0中的oracle用户的用户名与密码?
- Oracle透明网关软件 for 8i 哪里去下载?
- SELECT INTO问题:相同表结构复制出错-----00905: missing keyword (我是新手)
- dmp文件导入的存储过程实现方法。
- 求助group by a having count()问题
do loop
step := 5000;
vmax := 0;
v_sql := 'select sn,callid,tdata,xdata from tab_result where
sn > '||vmax||' and sn <= '||vmax||' + 6000';
get_cursor is for v_sql;
open get_cursor;
fetch into v_sn,v_callid,v_tdata,v_xdata;
exit get_cursor%nofound;
begin
v_ss := 'select callid from tab_detail where callid='||v_callid;
execute immediate v_ss into v_num;
begin
if v_num is not null then
v_sql2 := ' update tab_detail set sdata1 = v_tdata+v_callid,
sdata2 = v_data*100 + '||v_callid||', xdata= '||v_xdata||'+ '||v_tdata||' where callid = '||v_callid;
end if;
exception
if nodatafound
v_sql2 := 'insert into tab_detail(callid,sdata1,sdata2,xxdata) select '||v_callid||',b.tdata+b.callid ,b.tdata * 100 + b.callid ,b.xdata+b.tdata from tab_result b';
end;
execute immediate v_sql2;
if v_totalnum >= 6000 then
commit;
v_totalnum := 0;
vmax := vmax + step;
end if;
end;
end loop
v_sql2 := 'insert into tab_detail(callid,sdata1,sdata2,xxdata) select '||v_callid||',b.tdata+b.callid ,b.tdata * 100 + b.callid ,b.xdata+b.tdata from tab_result b where b.sn ='||v_sn;
using tab_result b
on a.callid=b.callid
WHEN MATCHED THEN
UPDATE
SET a.sdata1=b.tdata+b.cellid
WHEN NOT MATCHED THEN
INSERT
VALUES (值)
如果不用游标,我怎么才能从tab_result中获取每行数据呢?因为tab_result表中的数据是实时增加的.
do loop
step := 5000;
vmax := 0;
v_sql := 'select sn,callid,tdata,xdata from tab_result where
sn > '||vmax||' and sn <= '||vmax||' + 6000';
get_cursor is for v_sql;
open get_cursor;
fetch into v_sn,v_callid,v_tdata,v_xdata;
exit get_cursor%nofound;
begin
if v_callid = 101 then
xdata := xdata + 100;
elsif v_callid = 232 then
xdata := xdata + 2500;
elsif v_callid = 351 then
xdata := xdata + 3600;
else
return;
end if;
v_ss := 'select callid from tab_detail where callid='||v_callid;
execute immediate v_ss into v_num;
begin
if v_num is not null then
v_sql2 := ' update tab_detail set sdata1 = v_tdata+v_callid,
sdata2 = v_data*100 + '||v_callid||', xdata= '||v_xdata||'+ '||v_tdata||' where callid = '||v_callid;
end if;
exception
if nodatafound
v_sql2 := 'insert into tab_detail(callid,sdata1,sdata2,xxdata) select '||v_callid||',b.tdata+b.callid ,b.tdata * 100 + b.callid ,b.xdata+b.tdata from tab_result b where b.sn ='||v_sn; end;
execute immediate v_sql2;
if v_totalnum >= 6000 then
commit;
v_totalnum := 0;
vmax := vmax + step;
end if;
end;
end loop
case when callid=101 then xdata + 100
declare
type my_record is table of tab_result%rowtype;
v_callid number;begin
v_sql := 'select sn,callid,tdata,xdata from tab_result;
execute immedate v_sql bulk collect into my_record;
FOR i IN my_record.FIRST .. my_record.LAST LOOP
v_callid:= my_record(i).callid;
ls_sql := 'merge into tab_detail a using tab_result b on (a.callid = '||v_callid||')
when MATCHED THEN
UPDATE
SET a.sdata1=b.tdata+b.cellid
WHEN NOT MATCHED THEN
INSERT
VALUES (值)';
execute immediate ls_sql;
commit;
End LOOP;end;
算下来,一个存储过程要几百万次写
而我们的服务器是RAID5,写慢
所以我用SQL写出来,虽然SQL跑得慢,却是一次性写进去