PL/SQL Proc 性能调优

Posted

技术标签:

【中文标题】PL/SQL Proc 性能调优【英文标题】:PL/SQL Proc performance tuning 【发布时间】:2020-10-07 07:49:54 【问题描述】:

我在 proc 中有一个循环,它循环通过一个 ID。 CDID 可以有 4 种类型:

CDID      TYPE
123     AA
456     BB
789     CC
999     DD

每种类型都有 4 个主要的 IF 块。虽然 CDID 不必具有所有 4 种类型,并且每个主 IF 块都由嵌套的 if 块组成。 在嵌套的 ifs 中,我使用选择查询将值插入到 4 个变量(不是表)中。在所有 4 个 IF 块的末尾,有一个更新语句,它获取 4 个变量的值并更新表。

下面是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 分钟才能执行。在上面的proc中,对于每个cdid,它可以检查多个if。

我无法确定如何微调此过程。如何批量处理记录?

【问题讨论】:

希望你已经进行了search。没有任何帮助? 当你说approx. 30k-35k records 你指的是哪个表?您有可用于 id 列的索引吗? SQL 和 PL/SQL 之间的上下文切换代价高昂,因为检查 any 行是否存在的不必要计数也是如此。你在循环中得到了两个单独的选择。计数可以通过使用游标来解决。这也将使您的代码更清晰。 @0xdb...是的,我做到了。 @Sujitmohanty30... 它适用于 table_A,因为它必须遍历 table_a 的 id'f,然后对于每个 id,在嵌套的 if 块中对 table_b 运行 select。 【参考方案1】:

未经测试,但遵循@GloezTrol 在 cmets 中所说的内容,如下所示应该可以工作。使用按类型排序的单个游标,以便它以正确的顺序处理 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;

【讨论】:

谢谢...将对其进行测试并通知您。

以上是关于PL/SQL Proc 性能调优的主要内容,如果未能解决你的问题,请参考以下文章

系统性能调优学习笔记03

linux性能查看调优

linux性能优化实战-网络性能调优

Linux服务器性能查看分析调优

Linux服务器性能分析与调优

linux的性能调优