PL/SQL Proc性能调整
PL/SQL Proc performance tuning
我在 proc 中有一个循环,它循环通过一个 ID。 CDID 可以有 4 种类型:
CDID TYPE
123 AA
456 BB
789 CC
999 DD
每种类型有4个主要的IF块。尽管 CDID 没有必要拥有所有 4 种类型,并且每个主 IF 块都由嵌套的 if 块组成。
在嵌套的 ifs 中,我使用 select 查询将值插入 4 个变量(不是 table)。在所有 4 个 IF 块的末尾,有一个更新语句获取 4 个变量的值并更新 table.
下面是proc结构供大家参考:
CREATE OR REPLACE PROC MY_PROC
a varchar2;
b varchar2;
c varchar2;
d varchar2;
v_cnt number
BEGIN
FOR I IN (SELECT CDID FROM TABLE_A where column is null) --this table contains only 1 row for each id
BEGIN
select count(*) into v_cnt from TABLE_B where cdid=i.cdid and type='AA';
if v_count > 0 then
nested ifs
SELECT a,b,c,d INTO a,b,c,d from TABLE_B where cdid=i.cdid and type='AA'...;
end ifs...;
if v_count = 0 then --if count is zero of TYPE:AA
select count(*) into v_cnt from TABLE_B where cdid=i.cdid and type='BB';
if v_count > 0 then
nested ifs
select a,b,c,d INTO a,b,c,d from TABLE_B where cdid=i.cdid and type='BB'...;
end ifs...;
if v_count = 0 then --if count is zero of TYPE:BB
same thing continues for TYPES CC AND DD.
end if;
END;
UPDATE TABLE_A
SET COLUMN1=A,
COLUMN2=B,
COLUMN3=C,
COLUMN4=D
where cdid=i.cdid;
END LOOP;
END;
大约。 30k-35k 记录,proc 需要 40 分钟来执行。在上面的过程中,对于每个cdid,它可以检查多个if.
我无法确定如何微调此过程。如何批量处理记录?
未经测试,但根据@GloezTrol 在评论中所说的内容,类似下面的内容应该有效。使用按类型排序的单个游标,以便它以正确的顺序处理 IF。然后循环直到找到你想要的记录退出。
CREATE OR REPLACE PROC MY_PROC as
a varchar2(10); -- size these appropriately
b varchar2(10);
c varchar2(10);
d varchar2(10);
v_cnt number;
cursor loop_cur is
select *
from TABLE_B
where cdid=i.cdid
and type in ('AA','BB','CC','DD')
order by type asc;
BEGIN
FOR I IN (SELECT CDID FROM TABLE_A where column is null) --this table contains only 1 row for each id
BEGIN
-- good practice to re-initialize variables at start of loop
a := null;
b := null;
c := null;
d := null;
for v_row in loop_cur loop
if v_row.type = 'AA' then
nested ifs
a := v_row.a;
b := v_row.b;
c := v_row.c;
d := v_row.d;
exit; -- get out of the loop if there was a 'AA'
end ifs...;
if v_row.type = 'BB' then
nested ifs
a := v_row.a;
b := v_row.b;
c := v_row.c;
d := v_row.d;
exit; -- get out of the loop if there was a 'BB'
end ifs...;
end if
repeat for 'CC' and 'DD'
end loop;
END;
UPDATE TABLE_A
SET COLUMN1=A,
COLUMN2=B,
COLUMN3=C,
COLUMN4=D
where cdid=i.cdid;
END LOOP;
END;
我在 proc 中有一个循环,它循环通过一个 ID。 CDID 可以有 4 种类型:
CDID TYPE
123 AA
456 BB
789 CC
999 DD
每种类型有4个主要的IF块。尽管 CDID 没有必要拥有所有 4 种类型,并且每个主 IF 块都由嵌套的 if 块组成。 在嵌套的 ifs 中,我使用 select 查询将值插入 4 个变量(不是 table)。在所有 4 个 IF 块的末尾,有一个更新语句获取 4 个变量的值并更新 table.
下面是proc结构供大家参考:
CREATE OR REPLACE PROC MY_PROC
a varchar2;
b varchar2;
c varchar2;
d varchar2;
v_cnt number
BEGIN
FOR I IN (SELECT CDID FROM TABLE_A where column is null) --this table contains only 1 row for each id
BEGIN
select count(*) into v_cnt from TABLE_B where cdid=i.cdid and type='AA';
if v_count > 0 then
nested ifs
SELECT a,b,c,d INTO a,b,c,d from TABLE_B where cdid=i.cdid and type='AA'...;
end ifs...;
if v_count = 0 then --if count is zero of TYPE:AA
select count(*) into v_cnt from TABLE_B where cdid=i.cdid and type='BB';
if v_count > 0 then
nested ifs
select a,b,c,d INTO a,b,c,d from TABLE_B where cdid=i.cdid and type='BB'...;
end ifs...;
if v_count = 0 then --if count is zero of TYPE:BB
same thing continues for TYPES CC AND DD.
end if;
END;
UPDATE TABLE_A
SET COLUMN1=A,
COLUMN2=B,
COLUMN3=C,
COLUMN4=D
where cdid=i.cdid;
END LOOP;
END;
大约。 30k-35k 记录,proc 需要 40 分钟来执行。在上面的过程中,对于每个cdid,它可以检查多个if.
我无法确定如何微调此过程。如何批量处理记录?
未经测试,但根据@GloezTrol 在评论中所说的内容,类似下面的内容应该有效。使用按类型排序的单个游标,以便它以正确的顺序处理 IF。然后循环直到找到你想要的记录退出。
CREATE OR REPLACE PROC MY_PROC as
a varchar2(10); -- size these appropriately
b varchar2(10);
c varchar2(10);
d varchar2(10);
v_cnt number;
cursor loop_cur is
select *
from TABLE_B
where cdid=i.cdid
and type in ('AA','BB','CC','DD')
order by type asc;
BEGIN
FOR I IN (SELECT CDID FROM TABLE_A where column is null) --this table contains only 1 row for each id
BEGIN
-- good practice to re-initialize variables at start of loop
a := null;
b := null;
c := null;
d := null;
for v_row in loop_cur loop
if v_row.type = 'AA' then
nested ifs
a := v_row.a;
b := v_row.b;
c := v_row.c;
d := v_row.d;
exit; -- get out of the loop if there was a 'AA'
end ifs...;
if v_row.type = 'BB' then
nested ifs
a := v_row.a;
b := v_row.b;
c := v_row.c;
d := v_row.d;
exit; -- get out of the loop if there was a 'BB'
end ifs...;
end if
repeat for 'CC' and 'DD'
end loop;
END;
UPDATE TABLE_A
SET COLUMN1=A,
COLUMN2=B,
COLUMN3=C,
COLUMN4=D
where cdid=i.cdid;
END LOOP;
END;