"It" is slow again :-)The email explained a package to be slow.
Ok, I started with my "not enough information" reply and an email conversation began.
We are still not ready to identify the problem, but as there is no code instrumentation in place I tried to identify what's possible with
v$active_session_history (ASH).To do so, I created 2 Packages:
P1 and P2. P1 has a procedure DO_IT and a function SLEEP, which burns CPU for approximately x seconds. P2 only has a function SLEEP, which also burns CPU for approximately x seconds and then calls P1.SLEEP again. P1.DO_IT has a simple sql which calls P1.SLEEP and P2.SLEEP. My code is properly instrumented using DBMS_APPLICATION_INFO.set_module in the code and dbms_session.set_identifier to identify one specific execution - to compare it's value to the information already available in v$active_session_history.Here the packages:
CREATE OR REPLACE
PACKAGE P1
IS
PROCEDURE DO_IT(SEC IN NUMBER);
FUNCTION SLEEP(SEC IN NUMBER)
RETURN NUMBER;
END;
/
CREATE OR REPLACE
PACKAGE P2
IS
FUNCTION SLEEP(SEC IN NUMBER)
RETURN NUMBER;
END;
/
CREATE OR REPLACE PACKAGE BODY P1
IS
PROCEDURE DO_IT(SEC IN NUMBER)
IS
r NUMBER;
BEGIN
DBMS_APPLICATION_INFO.set_module(module_name => 'P1',
action_name => 'DO_IT');
dbms_output.put_line('++P1.DO_IT++');
SELECT P2.SLEEP(SEC) into r
FROM DUAL
WHERE P1.SLEEP(SEC) > 1;
dbms_output.put_line('--P1.DO_IT--');
DBMS_APPLICATION_INFO.set_module(module_name => 'blaaa',
action_name => 'blaaa');
END DO_IT;
FUNCTION SLEEP(SEC IN NUMBER)
RETURN NUMBER
IS
C NUMBER := 0;
now DATE := SYSDATE;
BEGIN
DBMS_APPLICATION_INFO.set_module(module_name => 'P1',
action_name => 'SLEEP');
dbms_output.put_line('++P1.SLEEP++');
LOOP
C := C + 1;
EXIT WHEN now + (SEC * (1/86400)) <= SYSDATE;
END LOOP;
dbms_output.put_line('--P1.SLEEP--');
DBMS_APPLICATION_INFO.set_module(module_name => 'blaaa',
action_name => 'blaaa');
RETURN C;
END SLEEP;
END;
/
CREATE OR REPLACE
PACKAGE BODY P2
IS
FUNCTION SLEEP(SEC IN NUMBER)
RETURN NUMBER
IS
C NUMBER := 0;
D NUMBER := 0;
now DATE := SYSDATE;
BEGIN
DBMS_APPLICATION_INFO.set_module(module_name => 'P2',
action_name => 'SLEEP');
dbms_output.put_line('++P2.SLEEP++');
LOOP
C := C + 1;
EXIT WHEN now + (SEC * (1/86400)) <= SYSDATE;
END LOOP;
SELECT P1.SLEEP(SEC) into D
FROM DUAL;
C := C + D;
dbms_output.put_line('--P2.SLEEP--');
DBMS_APPLICATION_INFO.set_module(module_name => 'blaaa',
action_name => 'blaaa');
RETURN C;
END SLEEP;
END;
/
I started the testcase with a simple
set serveroutput on exec dbms_session.set_identifier(client_id => 'berx testcase ' || to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') ); exec p1.do_it(5); exec dbms_session.set_identifier(client_id => 'berx testcase ' || to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') ); exec p1.do_it(5); exec dbms_session.set_identifier(client_id => 'blaaa');
And immediately afterwards I checked for sql_id, top_level_sql_id, action, module, client_id, plsql_entry_object_id, plsql_entry_subprogram_id, plsql_object and plsql_subprogram_id
select SESSION_ID,
sql_id,
( SELECT max( substr( sql_text , 1, 40 )) FROM v$sql sq WHERE sq.sql_id = ash.sql_id ) AS sql_text,
TOP_LEVEL_SQL_ID,
( SELECT max( substr( sql_text , 1, 40 )) FROM v$sql sq WHERE sq.sql_id = ash.top_level_sql_id ) AS top_level_sql_text,
action,
module,
client_id
, ( SELECT object_name FROM dba_procedures WHERE object_id = plsql_entry_object_id AND subprogram_id = 0) AS plsql_entry_object
, ( SELECT procedure_name FROM dba_procedures WHERE object_id = plsql_entry_object_id AND subprogram_id = plsql_entry_subprogram_id) AS plsql_entry_subprogram
, ( SELECT object_name FROM dba_procedures WHERE object_id = plsql_object_id AND subprogram_id = 0) AS plsql_object
, ( SELECT procedure_name FROM dba_procedures WHERE object_id = plsql_object_id AND subprogram_id = PLSQL_SUBPROGRAM_ID) AS plsql_subprogram
from v$active_session_history ash
where SAMPLE_TIME > sysdate - 1/(24*60)
and session_id = SYS_CONTEXT('USERENV','SID')
order by SAMPLE_TIME asc;
Here is the result (please excuse the wide list).
ST SESSION_ID SQL_ID SQL_TEXT TOP_LEVEL_SQL_ID TOP_LEVEL_SQL_TEXT ACTION MODULE CLIENT_ID PLSQL_ENTRY_OBJECT PLSQL_ENTRY_SUBPROGRAM PLSQL_OBJECT PLSQL_SUBPROGRAM ------------------- ---------- ------------- ---------------------------------------- ---------------- ---------------------------------------- ---------- ---------- ----------------------------------- ------------------------------ ------------------------------ --------------- ---------------- 2013-12-14 22:24:00 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:01 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:02 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT P1 SLEEP 2013-12-14 22:24:03 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT P1 SLEEP 2013-12-14 22:24:04 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:05 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:06 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:07 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:00 P1 DO_IT P2 SLEEP 2013-12-14 22:24:08 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:09 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:00 P1 DO_IT P2 SLEEP 2013-12-14 22:24:10 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:11 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT P1 SLEEP 2013-12-14 22:24:12 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:13 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT P1 SLEEP 2013-12-14 22:24:14 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:00 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:15 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:16 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:17 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:18 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 2013-12-14 22:24:19 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:20 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:15 P1 DO_IT P2 SLEEP 2013-12-14 22:24:21 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:15 P1 DO_IT P2 SLEEP 2013-12-14 22:24:22 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:15 P1 DO_IT STANDARD SYSDATE 2013-12-14 22:24:23 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:15 P1 DO_IT P2 SLEEP 2013-12-14 22:24:24 160 cqd77zbnpa79n SELECT P2.SLEEP(:B1 ) FROM DUAL WHERE P1 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P2 berx testcase 2013-12-14 22:24:15 P1 DO_IT P2 SLEEP 2013-12-14 22:24:25 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 2013-12-14 22:24:26 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 2013-12-14 22:24:27 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 2013-12-14 22:24:28 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 2013-12-14 22:24:29 160 cc9hp65m5aq6s SELECT P1.SLEEP(:B1 ) FROM DUAL 1ahw2g5n38js5 BEGIN p1.do_it(5); END; SLEEP P1 berx testcase 2013-12-14 22:24:15 P1 DO_IT P1 SLEEP 30 rows selected
So my findings here:
- TOP_LEVEL_SQL_ID is the same all the time. That's good, as I have a valid anchor on the top most layer.
- there is nothing similar to SQL_EXEC_ID for the TOP_LEVEL_SQL_ID. So I can not distinguish the 2 runs of P1.DO_IT.
- PLSQL_OBJECT.PLSQL_SUBPROGRAM does not always reflect the current application module, as also internal code (as SYSDATE) is shown there. ACTION and MODULE are more reliable.
- Only with ASH I don't see any general way to identify the runtime of sub-TOP_LEVEL SQLs or PLSQL_SUBPROGRAMs.
- The most complete picture from ASH is only given with proper instrumentation
- If you need the full insight about the stack of SQL and PL/SQL calls, you need to trace the session. This again works like a charm with ACTION and MODULE set and
DBMS_MONITOR.SERV_MOD_ACT_STAT_ENABLE

