如何在程序中找到 Ref Cursor 执行时间?
How to find Ref Cursor execution time in procedure?
我正在使用 Ref Cursor 作为 PLSQL Procedure 的输出参数。我需要在日志 table.
中维护 proc 的确切开始和结束时间
下面的伪代码:
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 分钟才能执行,但在日志 table 中我看到 STR_TIME 和 END_TIME 之间的区别只有少数秒。
如何捕获包括查询执行时间在内的过程所用的总时间?
您可以尝试将此程序拆分成两个打包程序,然后应用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;
一旦您的过程将引用游标交还给调用进程,它就无法知道它会发生什么。调用者甚至可能永远不会从游标中获取所有行。供调用者记录接下来发生的事情。
从程序内部无法分辨。 The OPEN FOR
statement:
... associates a cursor variable with a query, allocates database resources to process the query, identifies the result set, and positions the cursor before the first row of the result set.
在您的过程中,您所能花的时间就是生成查询文本需要多长时间以及打开 游标需要多长时间。然后过程结束,调用者接管 OUT ref 游标。你从这里看不到任何关于光标发生的事情。
调用方(大概)获取数据,这占用了大部分时间;但也可能在做其他处理。您需要调用者记录它调用您的过程与它完成它时关闭 ref 游标之间的时间 - 但这仍将包括它所做的任何其他处理,因此您无法从实际中分离出多少游标查询处理和提取。
如果这足够接近,那么如果您不希望调用者不得不担心它,那么您可能有第二个过程来关闭游标并记录时间。您可以让 'open' 游标在会话变量中记录开始时间(使包有状态)并让 'close' 过程检索它并插入日志记录;或者让 'open' 使用空结束时间初始插入到日志记录 table 中,然后让 'close' 使用实际结束时间更新该记录。但同样,这只是近似值。
如果您真的想在该过程中完成所有操作,那么您将不得不在其中进行所有查询处理,这可能意味着将游标批量收集到一个集合中,然后使用该集合类型作为 OUT 参数,调整您的调用者以迭代它而不是游标。那当然也有更多的内存开销,所以可能不实用。
我正在使用 Ref Cursor 作为 PLSQL Procedure 的输出参数。我需要在日志 table.
中维护 proc 的确切开始和结束时间下面的伪代码:
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 分钟才能执行,但在日志 table 中我看到 STR_TIME 和 END_TIME 之间的区别只有少数秒。
如何捕获包括查询执行时间在内的过程所用的总时间?
您可以尝试将此程序拆分成两个打包程序,然后应用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;
一旦您的过程将引用游标交还给调用进程,它就无法知道它会发生什么。调用者甚至可能永远不会从游标中获取所有行。供调用者记录接下来发生的事情。
从程序内部无法分辨。 The OPEN FOR
statement:
... associates a cursor variable with a query, allocates database resources to process the query, identifies the result set, and positions the cursor before the first row of the result set.
在您的过程中,您所能花的时间就是生成查询文本需要多长时间以及打开 游标需要多长时间。然后过程结束,调用者接管 OUT ref 游标。你从这里看不到任何关于光标发生的事情。
调用方(大概)获取数据,这占用了大部分时间;但也可能在做其他处理。您需要调用者记录它调用您的过程与它完成它时关闭 ref 游标之间的时间 - 但这仍将包括它所做的任何其他处理,因此您无法从实际中分离出多少游标查询处理和提取。
如果这足够接近,那么如果您不希望调用者不得不担心它,那么您可能有第二个过程来关闭游标并记录时间。您可以让 'open' 游标在会话变量中记录开始时间(使包有状态)并让 'close' 过程检索它并插入日志记录;或者让 'open' 使用空结束时间初始插入到日志记录 table 中,然后让 'close' 使用实际结束时间更新该记录。但同样,这只是近似值。
如果您真的想在该过程中完成所有操作,那么您将不得不在其中进行所有查询处理,这可能意味着将游标批量收集到一个集合中,然后使用该集合类型作为 OUT 参数,调整您的调用者以迭代它而不是游标。那当然也有更多的内存开销,所以可能不实用。