pl / sql存储过程...执行时间在哪里?

时间:2009-06-26 17:05:43

标签: performance oracle stored-procedures plsql

我目前正在跟踪存储过程中的性能泄漏。 在最初的“开始”之后立即输出时间戳,在最后的“结束”之前放置一个时间戳(我在之前执行提交)表示该过程需要abt。 10秒完成。 但是,我必须等待2分钟才能结束。

有人可以告诉我剩下的时间在哪里吗?我正在使用Oracle SQL dev但它似乎没有在其余时间闲置,程序似乎对相应的表保持锁定:(

非常感谢你提前启发......

编辑:再次感谢您的输入:) 这是程序的剥离代码,取决于要处理的项目数,第1部分当前需要abt。 10到40秒,第2节几毫秒。但是该过程需要2到8分钟才能运行。 另外,包含要删除的数据的表似乎被锁定的时间比需要的时间长,导致插入延迟。 按计划作业开始没什么区别btw,同样的行为。

create or replace
procedure MY_PROCEDURE is
start_procedure number;
start_delete number;
end_procedure number;
begin

  start_procedure :=dbms_utility.get_time;

  begin
  -- stripped: doing some selects/updates here
  end;
  commit;

  start_delete :=dbms_utility.get_time ;

  begin
  -- stripped: cleanig up some other data here
  end;
  commit;
  end_procedure :=dbms_utility.get_time ;

  dbms_output.put_line('procedure took: '||to_char((end_procedure- start_procedure)/1000));
  dbms_output.put_line('updates took: '||to_char((start_delete- start_procedure)/1000));
  dbms_output.put_line('delete took: '||to_char((end_procedure-start_delete)/1000));

end;

11 个答案:

答案 0 :(得分:3)

我认为你需要除以100,而不是1000(dbms_utility.get_time给出时间以厘秒为单位)。这应该给你100秒,大约2分钟。

但是,如果您有兴趣了解2分钟的执行时间,并且根据程序的复杂程度,您可能想要:

如果你有很多链接的PL / SQL过程调用,那么分析器可能会更好。如果在存储过程中主要有sql语句,那么statspack报告会更好。

以下是Profiler输出的内容:

Sample Report

Function Elapsed Time (microsecs) Data sorted by Total Subtree Elapsed Time (microsecs)

2831 microsecs (elapsed time) & 12 function calls
Subtree     Ind%    Function    Descendant  Ind%    Calls   Ind%    Function Name
2831    100%    93  2738    96.7%   2   16.7%   __plsq_vm
2738    96.7%   310     2428    85.8%   2   16.7%   __anonymous_block
2428    85.8%   15  2413    85.2%   1   8.3%    HR.TEST.TEST (Line 1)
2413    85.2%   435     1978    69.9%   3   25.0%   HR.TEST.TEST.FOO (Line 3)
1978    69.9%   1978    0   0.0%    3   25.0%   HR.TEST.__static_sql_exec_line5 (Line 5)
0   0.0%    0   0   0.0%    1   8.3%    SYS.DBMS_HPROF.STOP_PROFILING (Line 53)

答案 1 :(得分:3)

如果您通过以下消息替换对dbms_utility.get_time的调用:

dbms_output.put_line ('start procedure: ' || to_char(sysdate, HH24:MI:SS'));

然后调用这样的程序:

dbms_output.put_line ('before procedure: ' || to_char(sysdate, HH24:MI:SS'));
exec my_procedure;
dbms_output.put_line ('after procedure: ' || to_char(sysdate, HH24:MI:SS'));

然后会出现丢失时间的地方。

答案 2 :(得分:2)

我不熟悉pl / sql,但有没有办法在它运行时暂停或中断它?

你在浪费的时候击中它的几率等于它浪费的时间百分比,所以你可能需要多次停下来才能抓住它。通常问题出在调用堆栈中间的某个地方。如果您可以替换它,那么出现在多个堆栈样本上的任何内容都将为您节省大量时间。

In general, the method is this.

答案 3 :(得分:1)

声明部分可能会有一些需要很长时间才能执行的内容。你能包含存储过程的代码吗?

答案 4 :(得分:1)

在DBMS_OUTPUT语句中,您将结果除以1000.根据所有Oracle文档,我可以在dbms_utility.get_time函数上找到以100秒为单位的测量时间,而不是1000秒。

因此,当您显示10到40秒时,它实际上是100(1分40秒)到400(6分40秒)秒。这更符合您观察的2到8分钟。

查看http://download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_util.htm以获取有关该功能的更多信息。

答案 5 :(得分:0)

您的时间可能是由于SQL开发人员刷新屏幕时java和数据库之间的大量上下文切换。要测试它,请在SQLPlus中再次运行测试。要修复,请转到工具>偏好>数据库>高级参数和您的SQL数组获取大小到150到500之间的值,并且(如果您有适当的驱动程序)选中Use OCI / Thick驱动程序框。

答案 6 :(得分:0)

如果您有合适的权限(如果没有,请向您的dba寻求帮助)也许您可以查询以下视图:

V$SESSION_WAIT
V$SYSTEM_EVENT

然后您可以检查结果

here(http://www.remote-dba.net/oracle_10g_tuning/t_oracle_v $ session_wait.htm)*是关于如何读取输出的描述,以及关于内部事件的here is some more info

*你必须复制网址,因为$正在弄乱链接。

答案 7 :(得分:0)

这样的事情?

CREATE PROCEDURE ...
AS
DECLARE some stuff
BEGIN
    print time
    do stuff
    COMMIT
    print time
END

我对Oracle的事务范例知之甚少,但是我想知道在程序完成之前程序内部的提交是否真的没有任何影响,并且在到达END之前程序没有完成。此时,提交事务的实际过程开始,如果涉及触发器和引用完整性约束,则可能需要很长时间。

这种行为类似于DEFERRABLE INITALLY DEFERRED参照完整性约束的行为。

我怀疑建议的系统表查询会告诉您,或者您可以尝试单步执行交互式会话中的“执行内容”步骤,看看会发生什么。

答案 8 :(得分:0)

该程序有何作用? 一种可能的解释可能是DBMS_OUTPUT。 如果在SQL * Plus上执行SET SERVEROUTPUT ON,则在执行语句后,客户端会对使用DBMS_OUTPUT.PUT_LINE缓冲的任何信息进行“幕后”提取。我猜SQL Developer也是如此。

因此,如果很多东西被推送到DBMS_OUTPUT,那么程序的执行可能会很快,但是幕后收集可能会花费时间(特别是如果它是一个慢速网络)

SQL * Plus中的另一个技巧是你可以 SET TIMING ON(将自动显示语句的已用时间) 和 SET TIME ON(显示SQL提示中的时间)。

所以试试

SET SERVEROUTPUT OFF
SET TIMING ON
SET TIME ON
DBMS_MONITOR.DATABASE_TRACE_ENABLE(TRUE);
exec stored_proc;
disconn

看到结果。我不希望看到任何下落不明的时间。也就是说,客户应该报告整整两分钟。 假设确实如此,我将使用跟踪(DBMS_MONITOR命令)并在结果上运行tkprof以查看那些2分钟的帐户。

答案 9 :(得分:0)

问题解决了,但我还是不明白......

泄漏是由另一个程序中隐藏的错误选择语句引起的,该程序由另一个程序调用。我对它进行了优化,现在它就像魅力一样。

我找到了困难的方法,逐行评论......尝试和尝试。

但是,我仍然想知道为什么时间戳绝对不准确。这非常误导,花了我一段时间...... 那么,我创建时间戳的方式有什么问题吗?

如果有人有这方面的信息,我很高兴听到它。

感谢各位对此问题的帮助。

答案 10 :(得分:0)

Oracle包含一个分析器,它将告诉您在每个可执行语句上花费的时间。适用于10g及更早版本的dbms_profiler,并且11g中有一个更高级的版本(分层探查器)。

比使用dbms_utility和dbms_output语句集简单得多,它为您提供了更完整的信息 - 如果您有权查看其源代码,则可以深入了解被调用的例程。

我很高兴你解决了你的问题。但是,下次使用分析器会更容易。