[20260522]测试使用dbms_profiler.txt

[20260522]测试使用dbms_profiler.txt

--//使用dbms_profiler主要目的监测PL/SQL性能,自己从来没有使用过,看别人的例子,重复测试并做一个笔记。
--//参考链接:http://fritshoogland.wordpress.com/2012/11/26/profiling-plsql-with-dbms_profiler/

1.环境:
SCOTT@book01p> @ ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

2.执行proftab.sql脚本:

SCOTT@book01p> @?/rdbms/admin/proftab.sql
drop table plsql_profiler_data cascade constraints
           *
ERROR at line 1:
ORA-00942: table or view does not exist

drop table plsql_profiler_units cascade constraints
           *
ERROR at line 1:
ORA-00942: table or view does not exist


drop table plsql_profiler_runs cascade constraints
           *
ERROR at line 1:
ORA-00942: table or view does not exist


drop sequence plsql_profiler_runnumber
              *
ERROR at line 1:
ORA-02289: sequence does not exist

Table created.
Comment created.
Table created.
Comment created.
Table created.
Comment created.
Sequence created.
--//仔细看脚本很简单就是建立3个表,如果不需要就是删除3个表以及1个sequence。
--//drop table plsql_profiler_data cascade constraints;
--//drop table plsql_profiler_units cascade constraints;
--//drop table plsql_profiler_runs cascade constraints;
--//drop sequence plsql_profiler_runnumber;

3.测试:
--//参考链接:http://fritshoogland.wordpress.com/2012/11/26/profiling-plsql-with-dbms_profiler/
-- script: gtt_and_collection.sql
-- setup
set serveroutput on;
create global temporary table gtt ( col1 number, col2 varchar2(10) ) on commit preserve rows;
create or replace procedure insert_example is
        nr_to_loop number:=1000000;
        nr number:=0;
        type col_type is table of gtt%ROWTYPE;
        col col_type:=col_type();
begin
        dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));
        dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));
        for nr in 1..nr_to_loop loop

                /* gtt */
                insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );

                /* collection */
                col.extend;
                col(nr).col1 := nr;
                col(nr).col2 := 'AABBCCDDEE';

        end loop;
        commit;
        dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));
        dbms_profiler.stop_profiler;
end;
/
-- execute test
exec insert_example;
-- clean up
--drop procedure insert_example;
truncate table gtt;
drop table gtt;
--//已经写在脚本里面:
--//dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));
--//dbms_profiler.stop_profiler;

SCOTT@book01p> set serveroutput on;
SCOTT@book01p> exec insert_example;
Start: 09:42:34972
Stop: 09:43:34998
PL/SQL procedure successfully completed.
--//基本上需要1分钟完成测试。

4.分析:
$ cat  test_profiler.sql
COL owner FORMAT a16
COL name FORMAT a20
COL line FORMAT 9999
COL source FORMAT a88 WORD_WRAP
COL occurances FORMAT 9999999
COL tot_time_s FORMAT 999,999,990.999
COL run_comment FORMAT a40
COL pct FORMAT 999

SELECT runid, run_date, run_comment FROM plsql_profiler_runs;

SELECT u.unit_owner OWNER
        ,u.unit_name NAME
        ,d.line# LINE
        , (SELECT text
             FROM all_source
            WHERE     TYPE IN ('PACKAGE BODY'
                              ,'FUNCTION'
                              ,'PROCEDURE'
                              ,'TRIGGER')
                  AND name = u.unit_name
                  AND line = d.line#
                  AND owner = u.unit_owner
                  AND TYPE = u.unit_type)
            SOURCE
        ,d.total_occur OCCURANCES
        , (d.total_time / 1000000000) TOT_TIME_S
        ,d.total_time / r.run_total_time * 100 "PCT"
    FROM plsql_profiler_runs r, plsql_profiler_units u, plsql_profiler_data d
   WHERE     r.runid = &&runid
         AND r.runid = u.runid
         AND r.runid = d.runid
         AND d.unit_number = u.unit_number
         AND (d.total_time / 1000000000) > 1         --more than 1 second
ORDER BY tot_time_s
/
select (run_total_time/1000000000) tot_time_s from plsql_profiler_runs where runid=&runid;

SCOTT@book01p> @ test_profiler.sql

     RUNID RUN_DATE            RUN_COMMENT
---------- ------------------- ----------------------------------------
         1 2026-05-22 16:04:51 profiler run 202605221604

Enter value for runid: 1

OWNER      NAME                  LINE SOURCE                                                                                   OCCURANCES       TOT_TIME_S  PCT
---------- -------------------- ----- ---------------------------------------------------------------------------------------- ---------- ---------------- ----
SCOTT      INSERT_EXAMPLE          15 col.extend;                                                                                 1000000            1.348    5
SCOTT      INSERT_EXAMPLE          12 insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );                                   1000000           23.903   90


      TOT_TIME_S
----------------
          26.632

--//注解:AND (d.total_time / 1000000000) > 1 ,加入line排序字段。

SCOTT@book01p> @ test_profiler.sql

     RUNID RUN_DATE            RUN_COMMENT
---------- ------------------- ----------------------------------------
         1 2026-05-22 16:04:51 profiler run 202605221604

OWNER      NAME                  LINE SOURCE                                                                                   OCCURANCES       TOT_TIME_S  PCT
---------- -------------------- ----- ---------------------------------------------------------------------------------------- ---------- ---------------- ----
SCOTT      INSERT_EXAMPLE           1 procedure insert_example is                                                                       0            0.000    0
SCOTT      INSERT_EXAMPLE           2 nr_to_loop number:=1000000;                                                                       0            0.000    0
SCOTT      INSERT_EXAMPLE           3 nr number:=0;                                                                                     0            0.000    0
SCOTT      INSERT_EXAMPLE           5 col col_type:=col_type();                                                                         0            0.000    0
SCOTT      INSERT_EXAMPLE           7 dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));                 0            0.000    0
SCOTT      INSERT_EXAMPLE           8 dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));                                1            0.001    0
SCOTT      INSERT_EXAMPLE           9 for nr in 1..nr_to_loop loop                                                                1000001            0.055    0
SCOTT      INSERT_EXAMPLE          12 insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );                                   1000000           23.903   90
SCOTT      INSERT_EXAMPLE          15 col.extend;                                                                                 1000000            1.348    5
SCOTT      INSERT_EXAMPLE          16 col(nr).col1 := nr;                                                                         1000000            0.335    1
SCOTT      INSERT_EXAMPLE          17 col(nr).col2 := 'AABBCCDDEE';                                                               1000000            0.192    1
SCOTT      INSERT_EXAMPLE          20 commit;                                                                                           1            0.031    0
SCOTT      INSERT_EXAMPLE          21 dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));                                 1            0.000    0
SCOTT      INSERT_EXAMPLE          22 dbms_profiler.stop_profiler;                                                                      1            0.000    0
SCOTT      INSERT_EXAMPLE          23 end;                                                                                              0            0.000    0
15 rows selected.
--//基本可以看出循环测试比较多的地方,以及消耗时间比较多的情况。

      TOT_TIME_S
----------------
          26.632

5.另外的执行方式:
--//也可以放在pl/sql过程的外面,注解dbms_profiler相关行,重新建立存储过程。
create or replace procedure insert_example is
        nr_to_loop number:=1000000;
        nr number:=0;
        type col_type is table of gtt%ROWTYPE;
        col col_type:=col_type();
begin
        --dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));
        dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));
        for nr in 1..nr_to_loop loop

                /* gtt */
                insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );

                /* collection */
                col.extend;
                col(nr).col1 := nr;
                col(nr).col2 := 'AABBCCDDEE';

        end loop;
        commit;
        dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));
        --dbms_profiler.stop_profiler;
end;
/

SCOTT@book01p> set serveroutput on;
SCOTT@book01p> exec dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));
PL/SQL procedure successfully completed.

SCOTT@book01p> exec insert_example;
Start: 16:11:58305
Stop: 16:12:58331
PL/SQL procedure successfully completed.

SCOTT@book01p> exec dbms_profiler.stop_profiler
PL/SQL procedure successfully completed.

SCOTT@book01p> define runid=2
SCOTT@book01p> @ test_profiler.sql

     RUNID RUN_DATE            RUN_COMMENT
---------- ------------------- ----------------------------------------
         1 2026-05-22 16:04:51 profiler run 202605221604
         2 2026-05-22 16:11:41 profiler run 202605221611


OWNER            NAME                  LINE SOURCE                                                                                   OCCURANCES       TOT_TIME_S  PCT
---------------- -------------------- ----- ---------------------------------------------------------------------------------------- ---------- ---------------- ----
                    1                                                                                                   1            0.000    0
SCOTT            INSERT_EXAMPLE           1 procedure insert_example is                                                                       0            0.000    0
                    1                                                                                                   2            0.000    0
                    1                                                                                                   3            0.000    0
                    1                                                                                                   2            0.000    0
                    1                                                                                                   2            0.000    0
SCOTT            INSERT_EXAMPLE           2 nr_to_loop number:=1000000;                                                                       1            0.000    0
SCOTT            INSERT_EXAMPLE           3 nr number:=0;                                                                                     1            0.000    0
SCOTT            INSERT_EXAMPLE           5 col col_type:=col_type();                                                                         1            0.000    0
SCOTT            INSERT_EXAMPLE           8 dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));                                1            0.000    0
SCOTT            INSERT_EXAMPLE           9 for nr in 1..nr_to_loop loop                                                                1000001            0.052    0
SCOTT            INSERT_EXAMPLE          12 insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );                                   1000000           23.709   72
SCOTT            INSERT_EXAMPLE          15 col.extend;                                                                                 1000000            1.374    4
SCOTT            INSERT_EXAMPLE          16 col(nr).col1 := nr;                                                                         1000000            0.329    1
SCOTT            INSERT_EXAMPLE          17 col(nr).col2 := 'AABBCCDDEE';                                                               1000000            0.194    1
SCOTT            INSERT_EXAMPLE          20 commit;                                                                                           1            0.001    0
SCOTT            INSERT_EXAMPLE          21 dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));                                 1            0.000    0
SCOTT            INSERT_EXAMPLE          23 end;                                                                                              1            0.036    0
18 rows selected.

      TOT_TIME_S
----------------
          32.925


SELECT
 runid
,unit_number
,unit_type
,unit_owner
,unit_name
,to_char(unit_timestamp,'yyyy-mm-dd hh24:mi:ss')
,total_time
,spare1
,spare2
FROM plsql_profiler_units

     RUNID UNIT_NUMBER UNIT_TYPE        UNIT_OWNER   UNIT_NAME      TO_CHAR_UNIT_TIMEST TOTAL_TIME     SPARE1     SPARE2
---------- ----------- ---------------- ------------ -------------- ------------------- ---------- ---------- ----------
         1           1 PROCEDURE        SCOTT        INSERT_EXAMPLE 2026-05-22 16:04:33          0
         2           1 ANONYMOUS BLOCK        0000-00-00 00:00:00          0
         2           2 ANONYMOUS BLOCK        0000-00-00 00:00:00          0
         2           3 ANONYMOUS BLOCK        0000-00-00 00:00:00          0
         2           4 PROCEDURE        SCOTT        INSERT_EXAMPLE 2026-05-22 16:09:18          0
         2           5 ANONYMOUS BLOCK        0000-00-00 00:00:00          0
         2           6 ANONYMOUS BLOCK        0000-00-00 00:00:00          0
7 rows selected.
--//看RUNID=2的信息,就明白为什么前面在procedure insert_example is与nr_to_loop number:=1000000;出现

6.继续:
--//修改commit在循环体内。
create or replace procedure insert_example is
        nr_to_loop number:=1000000;
        nr number:=0;
        type col_type is table of gtt%ROWTYPE;
        col col_type:=col_type();
begin
        dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));
        dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));
        for nr in 1..nr_to_loop loop

                /* gtt */
                insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );

                /* collection */
                col.extend;
                col(nr).col1 := nr;
                col(nr).col2 := 'AABBCCDDEE';
                commit;
        end loop;
        dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));
        dbms_profiler.stop_profiler;
end;
/

SCOTT@book01p> exec insert_example;
Start: 16:29:59352
Stop: 16:30:59437
PL/SQL procedure successfully completed.

SCOTT@book01p> define runid=3
SCOTT@book01p> @ test_profiler.sql
     RUNID RUN_DATE            RUN_COMMENT
---------- ------------------- ----------------------------------------
         1 2026-05-22 16:04:51 profiler run 202605221604
         2 2026-05-22 16:11:41 profiler run 202605221611
         3 2026-05-22 16:29:12 profiler run 202605221629


OWNER            NAME                  LINE SOURCE                                                                                   OCCURANCES       TOT_TIME_S  PCT
---------------- -------------------- ----- ---------------------------------------------------------------------------------------- ---------- ---------------- ----
SCOTT            INSERT_EXAMPLE           1 procedure insert_example is                                                                       0            0.000    0
SCOTT            INSERT_EXAMPLE           2 nr_to_loop number:=1000000;                                                                       0            0.000    0
SCOTT            INSERT_EXAMPLE           3 nr number:=0;                                                                                     0            0.000    0
SCOTT            INSERT_EXAMPLE           5 col col_type:=col_type();                                                                         0            0.000    0
SCOTT            INSERT_EXAMPLE           7 dbms_profiler.start_profiler('profiler run '||to_char(sysdate,'yyyymmddhh24mi'));                 0            0.000    0
SCOTT            INSERT_EXAMPLE           8 dbms_output.put_line('Start: '||to_char(sysdate,'hh24:mi:sssss'));                                1            0.000    0
SCOTT            INSERT_EXAMPLE           9 for nr in 1..nr_to_loop loop                                                                1000001            0.125    0
SCOTT            INSERT_EXAMPLE          12 insert into gtt (col1, col2) values ( nr, 'AABBCCDDEE' );                                   1000000           49.029   58
SCOTT            INSERT_EXAMPLE          15 col.extend;                                                                                 1000000            2.100    2
SCOTT            INSERT_EXAMPLE          16 col(nr).col1 := nr;                                                                         1000000            0.456    1
SCOTT            INSERT_EXAMPLE          17 col(nr).col2 := 'AABBCCDDEE';                                                               1000000            0.296    0
SCOTT            INSERT_EXAMPLE          18 commit;                                                                                     1000000           31.460   37
SCOTT            INSERT_EXAMPLE          20 dbms_output.put_line('Stop: '||to_char(sysdate,'hh24:mi:sssss'));                                 1            0.000    0
SCOTT            INSERT_EXAMPLE          21 dbms_profiler.stop_profiler;                                                                      1            0.000    0
SCOTT            INSERT_EXAMPLE          22 end;                                                                                              0            0.000    0
15 rows selected.

      TOT_TIME_S
----------------
          84.652

--//可以看出commit在循环体内执行效率不高。

7.意外插曲:
--//看最后一次执行的显示:
SCOTT@book01p> exec insert_example;
Start: 16:29:59352
Stop: 16:30:59437
PL/SQL procedure successfully completed.
--//3次测试都是类似,start与stop的时间间隔都是60秒上下.而最后1次执行测试总时间是84.652.明显那里存在问题?

SCOTT@book01p> define runid=3
SCOTT@book01p> @ test_profiler.sql
     RUNID RUN_DATE            RUN_COMMENT
---------- ------------------- ----------------------------------------
         1 2026-05-22 16:04:51 profiler run 202605221604
         2 2026-05-22 16:11:41 profiler run 202605221611
         3 2026-05-22 16:29:12 profiler run 202605221629
....

--//RUNID,Start: 16:29:59352,而RUN_DATE记录确是2026-05-22 16:29:12.
--//实际上仔细看脚本作者原始脚本格式使用sssss,查询官方文档发现sssss表示Seconds past midnight (0-86399).
--//59437-59352 = 85,这样就非常接近了。

$ cat s2hms.sql
column "hh24:mi:ss" format a10
select to_char(to_date(&&1,'sssss'),'hh24:mi:ss') "hh24:mi:ss"  from dual;

SCOTT@book01p> @ s2hms 59352
hh24:mi:ss
----------
16:29:12
--//完成可以对上。
--//另外写一篇时间格式的说明.

请使用浏览器的分享功能分享到微信等