使用游标循环、插入和提交每一行的更有效方法 (Oracle)
More efficient way to use cursor loop, insert into and commit for each row (Oracle)
我在下面写了类似的东西(它有效),但在我的情况下,对于 150 万行,它并没有我需要的那么有效(它 运行 可能需要 2 天)
我看到了类似 BULK COLLECT FETCH FORALL 等的东西,但我无法在没有错误的情况下重写我的代码。你能帮我吗?
谢谢
--It is my code for rewriting
DECLARE
cnt NUMBER;
d_min NUMBER;
d_max NUMBER;
i NUMBER := 0;
CURSOR ts_metatata_cur IS select * from (select rownum as rn, id_profile from ts_metadata where typ=7 and per=3600 order by id_profile) where rn between 1 and 100000;
BEGIN
for metadata_rec in ts_metatata_cur
LOOP
XTS.GET_PROFILE_AGGR(metadata_rec.id_profile, cnt, d_min, d_max); --procedure with one IN parameter and three OUT parameter cnt, d_min, d_max
Execute immediate 'insert into TMP_PROFILES_OVERVIEW (id_profile, cnt, d_min, d_max) values (' || metadata_rec.id_profile || ', ' || cnt || ', ' || d_min || ', ' || d_max ||')';
i := i+1;
if (i > 10000) then
commit;
i := 0;
end if;
END LOOP;
commit;
END;
如果有必要,我在这里给出我调用的程序:
--this is procedure, which I call in my script
CREATE OR REPLACE PROCEDURE XTS.GET_PROFILE_AGGR(id_prof IN NUMBER, cnt OUT NUMBER, d_min OUT NUMBER, d_max OUT NUMBER)
AS
res varchar2(61);
BEGIN
select cluster_table_name into res FROM XTS.TIME_SERIES TS where TS.id=id_prof;
Execute immediate 'select nvl(count(*),0), nvl(min(time),0), nvl(max(time),0) from '|| res || ' where time_series_id=' || id_prof || ' ' into cnt, d_min, d_max;
EXCEPTION
when others then
null;
END;
在听取了其他人的建议后,我改变了处理任务的方法。我只插入分组数据而不是插入每一行。
像这样:
创建或替换过程XTS.GET_PROFILE_AGGR
作为
CURSOR time_series_cur 是 select 与 xts.time_serie 不同的 cluster_table_name;
BEGIN
for time_series_rec in time_series_cur
LOOP
Execute immediate 'INSERT INTO HDO.tmp_profiles_overview (id_profile, cnt, d_min, d_max) select time_series_id, count(*), min(time), max(time) from ' || time_series_rec.res || ' group by time_series_id';
END LOOP;
commit;
END;
我在下面写了类似的东西(它有效),但在我的情况下,对于 150 万行,它并没有我需要的那么有效(它 运行 可能需要 2 天) 我看到了类似 BULK COLLECT FETCH FORALL 等的东西,但我无法在没有错误的情况下重写我的代码。你能帮我吗?
谢谢
--It is my code for rewriting
DECLARE
cnt NUMBER;
d_min NUMBER;
d_max NUMBER;
i NUMBER := 0;
CURSOR ts_metatata_cur IS select * from (select rownum as rn, id_profile from ts_metadata where typ=7 and per=3600 order by id_profile) where rn between 1 and 100000;
BEGIN
for metadata_rec in ts_metatata_cur
LOOP
XTS.GET_PROFILE_AGGR(metadata_rec.id_profile, cnt, d_min, d_max); --procedure with one IN parameter and three OUT parameter cnt, d_min, d_max
Execute immediate 'insert into TMP_PROFILES_OVERVIEW (id_profile, cnt, d_min, d_max) values (' || metadata_rec.id_profile || ', ' || cnt || ', ' || d_min || ', ' || d_max ||')';
i := i+1;
if (i > 10000) then
commit;
i := 0;
end if;
END LOOP;
commit;
END;
如果有必要,我在这里给出我调用的程序:
--this is procedure, which I call in my script
CREATE OR REPLACE PROCEDURE XTS.GET_PROFILE_AGGR(id_prof IN NUMBER, cnt OUT NUMBER, d_min OUT NUMBER, d_max OUT NUMBER)
AS
res varchar2(61);
BEGIN
select cluster_table_name into res FROM XTS.TIME_SERIES TS where TS.id=id_prof;
Execute immediate 'select nvl(count(*),0), nvl(min(time),0), nvl(max(time),0) from '|| res || ' where time_series_id=' || id_prof || ' ' into cnt, d_min, d_max;
EXCEPTION
when others then
null;
END;
在听取了其他人的建议后,我改变了处理任务的方法。我只插入分组数据而不是插入每一行。
像这样:
创建或替换过程XTS.GET_PROFILE_AGGR
作为
CURSOR time_series_cur 是 select 与 xts.time_serie 不同的 cluster_table_name;
BEGIN
for time_series_rec in time_series_cur
LOOP
Execute immediate 'INSERT INTO HDO.tmp_profiles_overview (id_profile, cnt, d_min, d_max) select time_series_id, count(*), min(time), max(time) from ' || time_series_rec.res || ' group by time_series_id';
END LOOP;
commit;
END;