【问题标题】:long time run in procedure vs query block程序与查询块中长时间运行
【发布时间】:2022-01-22 23:32:12
【问题描述】:

我在性能或程序上有问题。 该过程有游标声明,然后是带有更新语句的循环体。 当我运行该程序时,运行所有行更新需要几个小时,但是当我将代码放入 toad 的匿名块中时,更新所有行需要 3 分钟! 代码之间没有区别,只是一个是在程序中,另一个是带有declear和body的块。 程序是这样的:

CREATE OR REPLACE procedure name_proc
is
    v_start_lvl number;
    v_level_nick varchar2(50);
    v_rec_id number;
    v_parent_type varchar2(3);
    path_desc_num varchar2(1000);
    delim_cut number;
    error_var number;
    cursor strt_lvl is            
        select REC_ID from WR_LEVELS_PATH
        where start_level=-1;
    
BEGIN
for rec in strt_lvl loop
begin
     begin 
     v_rec_id:=rec.rec_id;
     select tr_parent
     into v_start_lvl 
     from
        (select tr_parent 
         from WR_LEVEL_PARENTS_REF 
         where rec.rec_id=REC_ID and PARENT_TYPE in ('STS','STM')
         order by PARENT_TYPE)
     where rownum=1;
     
     if (v_start_lvl is not null)
     then
        begin 
           update WR_LEVELS_PATH
           set start_level=v_start_lvl
           where rec_id=rec.rec_id;
        end;
     end if;
 
end;
end loop;
commit;

end;

有人对此有解释吗?请!!!!

【问题讨论】:

  • 不同的执行计划,也许吧?还是您缺少的代码可能存在一些差异?它们更新的行数是否相同?

标签: sql oracle plsql oracle10g


【解决方案1】:

如果从过程中运行代码与从匿名 PL/SQL 块运行代码之间存在一致的差异,我认为您没有在问题中包含真正的原因。仅仅在一个过程中不会让你的代码变慢,更不用说慢很多倍了。

需要检查的一些事项:

  1. 快速和慢速运行在同一个执行环境中吗?即,您能否通过 SQL*Developer 手动进行两次调用来产生差异?

  2. 是否都使用相同的数据库用户运行?

  3. 两次运行是否使用相同的输入数据?即,您能否在每次运行后回滚,在两者之间切换,并始终保持一快一慢?

  4. 是否有其他用户(或者您拥有的另一个会话)在运行缓慢时可能将记录锁定在 WR_LEVELS_PATH 中?你知道如何检查数据库中的阻塞会话吗?

所有这些差异更有可能是罪魁祸首,而不是手术过程中的奇怪副作用。

此外,除非您为了简化问题而省略了重要的内容,否则您的程序代码似乎是不必要的。您可以使用单个 MERGE 语句完成所有这些逻辑:

MERGE INTO  wr_levels_paths t
USING (
  SELECT wlp.rec_id, wlpr.tr_parent
  FROM   wr_levels_paths wlp
  CROSS APPLY ( SELECT wlpr.tr_parent
                FROM   wr_level_parents_ref wlpr
                WHERE  wlpr.rec_id = wlp.rec_id
                AND    wlpr.parent_type IN ('STS','STM')
                ORDER BY wlpr.parent_type
                FETCH FIRST 1 ROW ONLY ) wlpr
  WHERE  wlp.start_level = -1
  AND    wlpr.tr_parent IS NOT NULL ) u
ON ( t.rec_id = u.rec_id )
WHEN MATCHED THEN UPDATE SET t.start_level = u.tr_parent;

【讨论】:

  • 1) 是的。快的和慢的在同一个执行环境中。 2)他们使用相同的数据库用户。 3)它们具有相同的输入数据并且也给出相同的输出数据。并更新相同的行数。 4)我是桌子上唯一的用户。并且没有阻止会话。我是唯一连接到架构的用户。谢谢你的回答...
  • 您以不同的顺序多次运行测试,以消除缓存影响作为原因?也许您应该发布一个完整的示例作为另一个问题 - 显示所有代码,然后在匿名块中执行(快速),然后立即回滚并在过程中执行(慢速)。
【解决方案2】:

1) 是的。快的和慢的在同一个执行环境中。 2)他们使用相同的数据库用户。 3)它们具有相同的输入数据并且也给出相同的输出数据。并更新相同的行数。 4)我是桌子上唯一的用户。并且没有阻止会话。我是唯一连接到架构的用户。谢谢你的回答...


rec_id 在列上有一个索引。也是独一无二的。并且是一个数字...

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多