首页 文章

如何在程序中找到Ref Cursor执行时间?

提问于
浏览
0

我正在使用Ref Cursor作为PLSQL过程的输出参数 . 我需要在日志表中维护proc的确切开始和结束时间 .

The dummy code below:

Procedure(P1 IN NUMBER, P_REF_CUR OUT SYS_REFCURSOR)
IS
V_TS TIMESTAMP;
BEGIN
V_TS := SYSTIMESTAMP;
<Business logic here to generate SELECT query for Ref Cursor...>;

OPEN P_REF_CUR FOR <SELECT QUERY>;

INSERT INTO LOG_TABLE(ID, STR_TIME,END_TIME,..) VALUES 
(1,V_TS,SYSTIMESTAMP,...);
END;

Ref Cursor的select查询有时需要2-3分钟才能执行,但在日志表中我看到STR_TIME和END_TIME之间的差异只有几秒钟 .

如何捕获过程所花费的总时间,包括查询执行时间?

3 回答

  • 1

    你无法从程序内部分辨出来 . The OPEN FOR statement

    ...将游标变量与查询相关联,分配数据库资源以处理查询,识别结果集,并将光标定位在结果集的第一行之前 .

    您可以在过程中花费的时间是生成查询文本需要多长时间以及打开游标所需的时间 . 然后程序结束,调用者接管OUT引用光标 . 你无法从这里看到光标发生了什么 .

    调用者(可能)获取数据,这占用了大部分时间;但也可能正在做其他处理 . 你需要调用者记录它调用你的程序和它完成后关闭ref光标的时间 - 但是它仍然包括它做的任何额外的处理,所以你不能分出实际的多少游标查询处理和获取 .

    如果它足够接近,那么如果您不希望调用者不必担心它,您可能会有第二个关闭光标并记录时间的过程 . 你可以让'open'游标在会话变量中记录开始时间(使包有状态)并让'close'过程检索并插入记录记录;或者让'open'以空的结束时间对日志表进行初始插入,然后使用实际结束时间记录的'close'更新 . 但同样,这只是近似的 .

    如果您真的想在该过程中完成所有操作,则必须在其中执行所有查询处理,这可能意味着将光标大量收集到集合中并使用该集合类型作为OUT参数,调整您的调用者以迭代而不是光标 . 当然,这也有更多的内存开销,所以可能不实用 .

  • 0

    一旦你的程序将ref光标移回调用进程,它就无法知道它会发生什么 . 调用者甚至可能永远不会从游标中获取所有行 . 调用者可以记录接下来发生的事情 .

  • 1

    您可以尝试将此过程拆分为两个打包过程,并应用 set timing on

    SQL> create or replace package myPkg is
            procedure pr1(P1 IN NUMBER);
            procedure pr2(P_REF_CUR OUT SYS_REFCURSOR);
    end;
    /
    
    SQL> create or replace package body myPkg is
        v_ts  timestamp;
      procedure pr1(P1 IN NUMBER) is
      begin
        v_ts := SYSTIMESTAMP;
        <Business logic here to generate SELECT query for Ref Cursor...>;  
      end;
    
      procedure pr2(P_REF_CUR OUT SYS_REFCURSOR) is
      begin
        open P_REF_CUR for <SELECT QUERY>;
        insert into log_table(ID, STR_TIME,END_TIME,..) values(1,V_TS,SYSTIMESTAMP,...);  
      end;  
    end;
    /
    
    SQL> set timing on;
    SQL> var v_p1 number:=107;
    SQL> var v_rc refcursor;
    SQL> exec myPkg.pr1( :v_p1 );
    
    PL/SQL procedure successfully completed
    
    Executed in 152,25 seconds
    
    SQL> exec myPkg.pr2( :v_rc );
    
    PL/SQL procedure successfully completed
    
    Executed in 12,34 seconds
    
    SQL> print v_rc;
    

相关问题