Oracle数据库中使用DBMS_PROFILER进行调优

Oracle数据库中使用DBMS_PROFILER进行调优

在进行数据库调优时,代码的性能瓶颈至关重要,Oracle数据库提供的DBMS_PROFILER包可以特别方便的发现瓶颈的所在之处。


DBMS_PROFILER在使用之前可能需要安装,具体安装步骤如下:

◆1:conn sys/oracle as sysdba
执行 @$ORACLE_HOME/rdbms/admin/profload.sql
◆2:创建一个用于存放跟踪信息的schema
CREATE USER profiler IDENTIFIED BY profiler DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT connect TO profiler;
CREATE PUBLIC SYNONYM plsql_profiler_runs FOR profiler.plsql_profiler_runs;
CREATE PUBLIC SYNONYM plsql_profiler_units FOR profiler.plsql_profiler_units;
CREATE PUBLIC SYNONYM plsql_profiler_data FOR profiler.plsql_profiler_data;
CREATE PUBLIC SYNONYM plsql_profiler_runnumber FOR profiler.plsql_profiler_runnumber;
grant resource to profiler;
◆3:使用刚刚创建的profiler用户执行如下脚本或代码:
conn profiler/profiler
@$ORACLE_HOME/rdbms/admin/proftab.sql
GRANT SELECT ON plsql_profiler_runnumber TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_data TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_units TO PUBLIC;
GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_runs TO PUBLIC;

 

安装成功后测试:

执行
create table a (a varhcar (200));
BEGIN
DBMS_PROFILER.START_PROFILER('123');
FOR I IN 1 .. 1000 LOOP
INSERT INTO A VALUES (I || '');
END LOOP;
COMMIT;
DBMS_PROFILER.STOP_PROFILER();
END;
/
执行后使用下面的代码检查:

SELECT C.LINE#, C.TOTAL_OCCUR, C.TOTAL_TIME, C.MIN_TIME, C.MAX_TIME
FROM PLSQL_PROFILER_RUNS A, PLSQL_PROFILER_UNITS B, PLSQL_PROFILER_DATA C
WHERE A.RUN_COMMENT = '123'
AND B.UNIT_OWNER = ''
AND A.RUNID = B.RUNID
AND A.RUNID = C.RUNID
AND B.UNIT_NUMBER = C.UNIT_NUMBER;

注意:每次DBMS_PROFILER.START_PROFILER的输入参数需要改变,否则便不能分别运行后的运行结果了。

除此之外B.UNIT_OWNER =''中的约束值如果是在package里面需要是包名,如果是procedure则是procedure的名字。实在在不知道什么名字时可以在PLSQL_PROFILER_UNITS中查一下。
     LINE# TOTAL_OCCUR TOTAL_TIME   MIN_TIME   MAX_TIME
---------- ----------- ---------- ---------- ----------
         1           0          0          0          0
         2           0          0          0          0
         3        1001    1842000       1000      35000
         4        1000   38527000      32000    3717000
         6           1     250000     250000     250000
         7           1       7000       7000       7000
         8           0          0          0          0

7 rows selected.
create or replace procedure TEST_PROFILER AS
BEGIN
DBMS_PROFILER.START_PROFILER('123');
FOR I IN 1 .. 1000 LOOP
INSERT INTO A VALUES (I || '');
END LOOP;
COMMIT;
DBMS_PROFILER.STOP_PROFILER();
END;
col text format a40
SELECT C.LINE#, D.TEXT,C.TOTAL_OCCUR, C.TOTAL_TIME, C.MIN_TIME, C.MAX_TIME
FROM PLSQL_PROFILER_RUNS A, PLSQL_PROFILER_UNITS B, PLSQL_PROFILER_DATA C,user_source D
WHERE A.RUN_COMMENT = '123'
AND B.UNIT_OWNER = 'PROFILER'
AND A.RUNID = B.RUNID
AND A.RUNID = C.RUNID
AND B.UNIT_NUMBER = C.UNIT_NUMBER
and d.name=B.UNIT_NAME
and d.line=c.line#
and B.UNIT_NAME='TEST_PROFILER';


    LINE# TEXT                                     TOTAL_OCCUR TOTAL_TIME   MIN_TIME   MAX_TIME
---------- ---------------------------------------- ----------- ---------- ---------- ----------
         1 procedure TESTPRROFILER AS                         0          0          0          0
         3 DBMS_PROFILER.START_PROFILER('123');               0          0          0          0
         4 FOR I IN 1 .. 1000 LOOP                         1001    1810000       1000      17000
         5 INSERT INTO A VALUES (I || '');                 1000   36421000      32000     897000
         7 COMMIT;                                            1     224000     224000     224000
         8 DBMS_PROFILER.STOP_PROFILER();                     1       7000       7000       7000
         9 END;                                               0          0          0          0
conn lt/lt
begin
DBMS_PROFILER.START_PROFILER('123');
inserttab2(1000,100);
DBMS_PROFILER.STOP_PROFILER();
end;
/
col text format a50
SELECT C.LINE#, D.TEXT,C.TOTAL_OCCUR, C.TOTAL_TIME, C.MIN_TIME, C.MAX_TIME
FROM PLSQL_PROFILER_RUNS A, PLSQL_PROFILER_UNITS B, PLSQL_PROFILER_DATA C,user_source D
WHERE A.RUN_COMMENT = '123'
AND B.UNIT_OWNER = 'LT'
AND A.RUNID = B.RUNID
AND A.RUNID = C.RUNID
AND B.UNIT_NUMBER = C.UNIT_NUMBER
and d.name=B.UNIT_NAME
and d.line=c.line#
and B.UNIT_NAME='INSERTTAB2';

     LINE# TEXT                                               TOTAL_OCCUR TOTAL_TIME   MIN_TIME   MAX_TIME
---------- -------------------------------------------------- ----------- ---------- ---------- ----------
         1 procedure inserttab2(rowc NUMBER,colc NUMBER)                0       4000       4000       4000
         3 buf varchar(24000):='insert into tcol'||to_char(co           1      28000      28000      28000
           lc)||' select level,';
         5  for i in 1..colc-1                                        100     178000       1000      11000
         7    buf:=buf||'mod(level+'||to_char(i)||',1e10),';           99     253000       1000      18000
         9  buf:=buf||'mod(level+'||to_char(colc)||',1e10) fr           1       3000       3000       3000
           om dual connect by level<='||to_char(rowc);
        10  execute immediate buf;                                      1  107750000  107750000  107750000
        11 end;                                                         1       7000       7000       7000
begin
DBMS_PROFILER.START_PROFILER('123');
comp_join2(3,2);
DBMS_PROFILER.STOP_PROFILER();
end;
/
col text format a50
SELECT C.LINE#, D.TEXT,C.TOTAL_OCCUR, C.TOTAL_TIME, C.MIN_TIME, C.MAX_TIME
FROM PLSQL_PROFILER_RUNS A, PLSQL_PROFILER_UNITS B, PLSQL_PROFILER_DATA C,user_source D
WHERE A.RUN_COMMENT = '123'
AND B.UNIT_OWNER = 'LT'
AND A.RUNID = B.RUNID
AND A.RUNID = C.RUNID
AND B.UNIT_NUMBER = C.UNIT_NUMBER
and d.name=B.UNIT_NAME
and d.line=c.line#
and B.UNIT_NAME='COMP_JOIN2';
     LINE# TEXT                                               TOTAL_OCCUR TOTAL_TIME   MIN_TIME   MAX_TIME
---------- -------------------------------------------------- ----------- ---------- ---------- ----------
         1 procedure                                                    0      14000      14000      14000
         3 buf varchar(100):='';                                        1       3000       3000       3000
         9 start_time := DBMS_UTILITY.get_time;                         1     520000     520000     520000
        10 execute immediate 'truncate table tcol50';                   1    2462000    2462000    2462000
        11 execute immediate 'drop index tcol50_idx';                   1    3016000    3016000    3016000
        12 execute immediate 'drop table tcoll';                        1     729000     729000     729000
        13 execute immediate 'drop table tcolr';                        1     770000     770000     770000
        14 inserttab2(10000*tm,50);                                     1      68000      68000      68000
        15 commit;                                                      1    2597000    2597000    2597000
        16 execute immediate 'create table tcoll as select x1           1    7254000    7254000    7254000
           ,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v1
           5,v16,v17,v18,v19,v20,v21,v22,v23,v24,v25 from tco
           l50';
        17 execute immediate 'create table tcolr as select x1           1    5343000    5343000    5343000
           ,v25,v26,v27,v28,v29,v30,v31,v32,v33,v34,v35,v36,v
           37,v38,v39,v40,v41,v42,v43,v44,v45,v46,v47,v48,v49
           ,v50 from tcol50';
        18 execute immediate 'create index tcoll_idx on tcoll           1    5400000    5400000    5400000
           (x1)';
        19 execute immediate 'create index tcolr_idx on tcolr           1    4491000    4491000    4491000
           (x1)';
        20 execute immediate 'create index tcol50_idx on tcol           1    3840000    3840000    3840000
           50(x1)';
        21 end_time := DBMS_UTILITY.get_time;                           1       8000       8000       8000
        22 DBMS_OUTPUT.PUT_LINE('init '||to_char(end_time-sta           1     585000     585000     585000
           rt_time));
        23 for i in 1..tm2                                              3       6000       2000       2000
        25 start_time := DBMS_UTILITY.get_time;                         2       4000       2000       2000
        26 select sum(v1)||sum(v20)||sum(v30)||sum(v40)||sum(           2   39127000   17665000   21462000
           v50) into buf from tcol50;
        27 end_time := DBMS_UTILITY.get_time;                           2      16000       8000       8000
        28 DBMS_OUTPUT.PUT_LINE('single '||to_char(end_time-s           2      39000      19000      20000
           tart_time));
        29 start_time := DBMS_UTILITY.get_time;                         2       4000       2000       2000
        30 select sum(v1)||sum(v20)||sum(v30)||sum(v40)||sum(           2  170020000   73297000   96723000
           v50) into buf from tcoll a,tcolr b where a.x1=b.x1
           ;
        31 end_time := DBMS_UTILITY.get_time;                           2      16000       8000       8000
        32 DBMS_OUTPUT.PUT_LINE('two join '||to_char(end_time           2      38000      19000      19000
           -start_time));
        33 start_time := DBMS_UTILITY.get_time;                         2       3000       1000       2000
        34 select /*+ rule */ sum(v1)||sum(v20)||sum(v30)||su           2  190600000   87969000  102631000
           m(v40)||sum(v50) into buf from tcoll a,tcolr b whe
           re a.x1=b.x1;
        35 end_time := DBMS_UTILITY.get_time;                           2      17000       8000       9000
        36 DBMS_OUTPUT.PUT_LINE('two join '||to_char(end_time           2      38000      19000      19000
           -start_time));
        38 end;                                                         1       4000       4000       4000
oracle 10.2.0.1的输出与11g不同,时间后3个数不全为0

 

     LINE# TEXT                                               TOTAL_OCCUR TOTAL_TIME   MIN_TIME   MAX_TIME
---------- -------------------------------------------------- ----------- ---------- ---------- ----------
         1 procedure inserttab2(rowc NUMBER,colc NUMBER)                0       4677       4677       4677
         3 buf varchar(24000):='insert into tcol'||to_char(co           1      10540      10540      10540
           lc)||' select level,';

         5 for i in 1..colc-1                                         100      77774        712       5506
         7    buf:=buf||'level+'||to_char(i)||',';                     99     165151       1285       8028
         9 buf:=buf||'level+'||to_char(colc)||' from dual con           1       3703       3703       3703
           nect by level<='||to_char(rowc);

        10 execute immediate buf;                                       1   59824304   59824304   59824304
        11 end;                                                         1       3144       3144       3144
dbms_profiler用来测试PL/SQL代码非常有用,比如找出哪一段代码比较耗时,也可以用来比较不同算法之间的差异。
1.配置dbms_profiler的运行环境
SQL> conn / as sysdba
已连接。
SQL> @?\rdbms\admin\profload.sql
程序包已创建。

授权成功。

同义词已创建。

库已创建。

程序包主体已创建。
Testing for correct installation
SYS.DBMS_PROFILER successfully loaded.
PL/SQL 过程已成功完成。
SQL> @?\rdbms\admin\proftab.sql
drop table plsql_profiler_data cascade constraints
           *
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在

drop table plsql_profiler_units cascade constraints
           *
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在

drop table plsql_profiler_runs cascade constraints
           *
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在

drop sequence plsql_profiler_runnumber
              *
ERROR 位于第 1 行:
ORA-02289: 序列(号)不存在

表已创建。

注释已创建。

表已创建。

注释已创建。

表已创建。

注释已创建。

序列已创建。
SQL> @?\plsql\demo\profrep.sql
视图已建立。

视图已建立。

视图已建立。

视图已建立。

程序包已创建。
没有错误。
程序包主体已创建。
没有错误。
SQL>
2.使用dbms_profiler
e.g.:
begin
    dbms_profiler.start_profiler( 'mod' );
    for i in 1 .. 500000
    loop
        cnt := cnt + 1;
        if ( mod(cnt,1000) = 0 )
        then
            commit;
        end if;
    end loop;
    dbms_profiler.stop_profiler;
end;
/
begin
    dbms_profiler.start_profiler( 'no mod' );
    for i in 1 .. 500000
    loop
        cnt := cnt + 1;
        if ( cnt = 1000 )
        then
            commit;
            cnt := 0;
        end if;
    end loop;
    dbms_profiler.stop_profiler;
end;
/
然后执行:
SQL> conn scott/tiger@db01
已连接。
SQL> exec no_mod
PL/SQL 过程已成功完成。
SQL> exec do_mod
PL/SQL 过程已成功完成。
3.生成Report
Oracle自带的profsum.sql比较耗时,可以使用tom修改过的profsum.sql脚本来生成Report。
Oracle自带的profsum.sql脚本产生的Report比Tom的profsum.sql脚本所产生的Report详细,具体的结果请查看示例。
每次执行profsum.sql脚本之前,需要把旧的数据删除:
truncate table plsql_profiler_data;
truncate table plsql_profiler_units;
truncate table plsql_profiler_runs;
Oracle自带的profsum.sql比较耗时


profsum.sql脚本


Rem
Rem $Header: profsum.sql 13-apr-98.19:17:28 astocks Exp $
Rem
Rem profsum.sql
Rem
Rem  Copyright (c) Oracle Corporation 1998, 1999. All Rights Reserved.
Rem
Rem    NAME
Rem      profsum.sql
Rem
Rem    DESCRIPTION
Rem      Example of usage of profiler data. A miscellany of potentially
Rem      useful adhoc queries, and calls to the prof_report_utilities
Rem      package.
Rem
Rem    NOTES
Rem      You must connect before running this script.  Calls to the long
Rem      reports can be commented out.
Rem
/* Script. to dump lots of reports from ordts long performance run */
set echo off
set linesize 5000
set trimspool on
set serveroutput on
set termout off
column owner format a11
column unit_name format a14
column text format a21 word_wrapped
column runid format 999999
column secs  format 99999.99
column hsecs format 99999.99
column grand_total  format 9999.99
column run_comment format a11 word_wrapped
column line# format 99999
column pct format 9999.9
column unit_owner format a11
spool profsum.out
/* Clean out rollup results, and recreate */
update plsql_profiler_units set total_time = 0;
execute prof_report_utilities.rollup_all_runs;
/* Total time */
select
    to_char(grand_total/1000000000, '999999.99') as grand_total
  from plsql_profiler_grand_total;
/* Total time spent on each run */
select
    runid, substr(run_comment,1, 30) as run_comment,
    run_total_time/1000000000 as seconds
  from plsql_profiler_runs
  where run_total_time > 0
  order by runid asc;

/* Percentage of time in each module, for each run separately */
select
    p1.runid,
    substr(p2.run_comment, 1, 20) as run_comment,
    p1.unit_owner,
    decode(p1.unit_name, '', '', substr(p1.unit_name,1, 20)) as unit_name,
    TO_CHAR(p1.total_time/1000000000, '99999.99') as seconds,
    TO_CHAR(100*p1.total_time/p2.run_total_time, '999.9') as percentage
  from plsql_profiler_units p1, plsql_profiler_runs p2
  where
    p1.runid=p2.runid and
    p1.total_time > 0 and p2.run_total_time > 0 and 
    (p1.total_time/p2.run_total_time)  >= .01
  order by p1.runid asc, p1.total_time desc;
/* Percentage of time in each module, summarized across runs */
select p1.unit_owner,
    decode(p1.unit_name, '', '', substr(p1.unit_name,1, 25)) as unit_name,
    TO_CHAR(p1.total_time/1000000000, '99999.99') as seconds,
    TO_CHAR(100*p1.total_time/p2.grand_total, '99999.99') as percentage
  from
    plsql_profiler_units_cross_run p1,
    plsql_profiler_grand_total p2
  order by p1.total_time DESC;

Rem Analyze min/max/average time anomalies -
Rem
Rem This report finds lines where the minimum time for the query is either
Rem greater than the average time (which indicates a data collection
Rem problem), or significantly less than the average (which indicates high
Rem variablility in the timing of a single line). It can take a long time to
Rem run, so it should only be used if the data is suspected to have problems.
Rem Normally, this query should produce no output.
Rem
select
    p1.runid, p2.unit_owner, substr(p2.unit_name,1,25),
    to_char(p1.line#,'9999') as line,
    p1.total_occur,
    to_char(p1.total_time/1000,'9999999.99') as microS,
    to_char(p1.total_time/(1000*p1.total_occur),'9999999.99') as "Ave Micro",
    to_char(p1.min_time/1000,'9999999.99') as min_time,
    to_char(p1.max_time/1000,'999999999.99') as max_time,
    to_char(p1.max_time/p1.min_time,'999999.99') as "Max/min",
    to_char(p1.total_time/(p1.total_occur*p1.min_time),'99999.99')as "Ave/min",
    p3.text
  from
    plsql_profiler_data p1,
    plsql_profiler_units p2,
    all_source p3
  where
    ((p1.total_time > 1000*(p1.total_occur*p1.min_time)) OR
     (p1.total_time < (p1.total_occur*p1.min_time))) AND
    p1.runID=p2.runID and p2.unit_number = p1.unit_number AND
    ((p3.type='PACKAGE BODY') OR (p3.type = 'PROCEDURE')) and
    p3.line = p1.line# and
    (p3.owner = p2.unit_owner)   AND
    (p3.name=p2.unit_name)
  order by "Ave/min" asc;
/* Lines taking more than 1% of the total time, each run separate */
select
    p1.runid as runid,
    to_char(p1.total_time/1000000000, '99999.9') as seconds,
    substr(p2.unit_owner, 1, 20) as owner,
    decode(p2.unit_name, '', '', substr(p2.unit_name,1, 20)) as unit_name,
    p1.line#,
    p3.text
  from
    plsql_profiler_data p1,
    plsql_profiler_units p2,
   all_source p3, plsql_profiler_grand_total p4
  where
    (p1.total_time >= p4.grand_total/100) AND
    p1.runID = p2.runid and
    p2.unit_number=p1.unit_number and
    p3.type='PACKAGE BODY' and
    p3.owner = p2.unit_owner and
    p3.line = p1.line# and
    p3.name=p2.unit_name
  order by p1.total_time desc;
/* Most popular lines (more than 1%), summarize across all runs */
select
    to_char(p1.total_time/1000000000, '99999.9') as seconds,
    substr(p1.unit_owner, 1, 20) as unit_owner,
    decode(p1.unit_name, '', '', substr(p1.unit_name,1, 20)) as unit_name,
    p1.line#,
    p3.text
  from
    plsql_profiler_lines_cross_run p1,
    all_source p3,
    plsql_profiler_grand_total p4
  where
    (p1.total_time >= p4.grand_total/100) AND
    ((p3.type='PACKAGE BODY') OR (p3.type = 'PROCEDURE')) and
    (p3.line = p1.line#) and
    (p3.owner = p1.unit_owner) AND
    (p3.name = p1.unit_name)
  order by p1.total_time desc;
Rem Get coverage information
execute prof_report_utilities.rollup_all_runs;
Rem Number of lines actually executed in different units (by unit_name)
select
    p1.unit_owner, p1.unit_name,
    count(p1.line#) as lines_executed
  from plsql_profiler_lines_cross_run p1
  where
    (p1.unit_type = 'PACKAGE BODY' OR
    p1.unit_type = 'TYPE BODY')  AND
    p1.total_occur != 0
  group by p1.unit_owner, p1.unit_name;

Rem Total number of lines in different units ( by unit_name)
select
    p1.unit_owner, p1.unit_name,
    count(p1.line#) as lines_present
  from plsql_profiler_lines_cross_run p1
  where
    (p1.unit_type = 'PACKAGE BODY' OR
    p1.unit_type = 'TYPE BODY')
    group by p1.unit_owner, p1.unit_name;

Rem Number of lines actually executed for all units
select
    count(p1.line#) as lines_executed
  from plsql_profiler_lines_cross_run p1
  where
    (p1.unit_type = 'PACKAGE BODY' OR
     p1.unit_type = 'TYPE BODY')  AND
    p1.total_occur > 0;


Rem Total number of lines in all units
select
    count(p1.line#) as lines_present
  from plsql_profiler_lines_cross_run p1
  where
    (p1.unit_type = 'PACKAGE BODY' OR
     p1.unit_type = 'TYPE BODY')  ;
/* Full reports */
execute prof_report_utilities.Print_Detailed_Report;
execute prof_report_utilities.Print_Summarized_Report;
spool off
set termout on
edit profsum.out
set linesize 131
om的profsum.sql脚本

 

set echo off
set linesize 5000
set trimspool on
set serveroutput on
set termout off
column owner format a11
column unit_name format a14
column text format a21 word_wrapped
column runid format 999999
column secs  format 99999.99
column hsecs format 99999.99
column grand_total  format 9999.99
column run_comment format a11 word_wrapped
column line# format 99999
column pct format 9999.9
column unit_owner format a11
spool profsum.out
/* Clean out rollup results, and recreate */
update plsql_profiler_units set total_time = 0;
execute prof_report_utilities.rollup_all_runs;
prompt =
prompt =
prompt ====================
prompt Total time
select grand_total/1000000000 as grand_total
  from plsql_profiler_grand_total;
prompt =
prompt =
prompt ====================
prompt Total time spent on each run
select runid,
       substr(run_comment,1, 30) as run_comment,
       run_total_time/1000000000 as secs
  from (select a.runid, sum(a.total_time)  run_total_time, b.run_comment
          from plsql_profiler_units a, plsql_profiler_runs b
         where a.runid = b.runid group by a.runid, b.run_comment )
where run_total_time > 0
order by runid asc;

prompt =
prompt =
prompt ====================
prompt Percentage of time in each module, for each run separately
select p1.runid,
       substr(p2.run_comment, 1, 20) as run_comment,
       p1.unit_owner,
       decode(p1.unit_name, '', '',
                    substr(p1.unit_name,1, 20)) as unit_name,
       p1.total_time/1000000000 as secs,
       TO_CHAR(100*p1.total_time/p2.run_total_time, '999.9') as percentage
  from plsql_profiler_units p1,
       (select a.runid, sum(a.total_time)  run_total_time, b.run_comment
          from plsql_profiler_units a, plsql_profiler_runs b
         where a.runid = b.runid group by a.runid, b.run_comment ) p2
where p1.runid=p2.runid
   and p1.total_time > 0
   and p2.run_total_time > 0
   and  (p1.total_time/p2.run_total_time)  >= .01
order by p1.runid asc, p1.total_time desc;
column secs form. 99999.99
prompt =
prompt =
prompt ====================
prompt Percentage of time in each module, summarized across runs
select p1.unit_owner,
       decode(p1.unit_name, '', '', substr(p1.unit_name,1, 25)) as
unit_name,
       p1.total_time/1000000000 as secs,
       TO_CHAR(100*p1.total_time/p2.grand_total, '99999.99') as percentage
  from plsql_profiler_units_cross_run p1,
       plsql_profiler_grand_total p2
order by p1.total_time DESC;

prompt =
prompt =
prompt ====================
prompt Lines taking more than 1% of the total time, each run separate
select p1.runid as runid,
       p1.total_time/10000000 as Hsecs,
        p1.total_time/p4.grand_total*100 as pct,
       substr(p2.unit_owner, 1, 20) as owner,
       decode(p2.unit_name, '', '', substr(p2.unit_name,1, 20)) as
unit_name,
       p1.line#,
       ( select p3.text
           from all_source p3
          where p3.owner = p2.unit_owner and
                p3.line = p1.line# and
                p3.name=p2.unit_name and
                p3.type not in ( 'PACKAGE', 'TYPE' )) text
  from plsql_profiler_data p1,
       plsql_profiler_units p2,
       plsql_profiler_grand_total p4
where (p1.total_time >= p4.grand_total/100)
   AND p1.runID = p2.runid
   and p2.unit_number=p1.unit_number
order by p1.total_time desc;
prompt =
prompt =
prompt ====================
prompt Most popular lines (more than 1%), summarize across all runs
select p1.total_time/10000000 as hsecs,
        p1.total_time/p4.grand_total*100 as pct,
       substr(p1.unit_owner, 1, 20) as unit_owner,
       decode(p1.unit_name, '', '',
                 substr(p1.unit_name,1, 20)) as unit_name,
       p1.line#,
       ( select p3.text from all_source p3
          where (p3.line = p1.line#) and
                (p3.owner = p1.unit_owner) AND
                (p3.name = p1.unit_name) and
                (p3.type not in ( 'PACKAGE', 'TYPE' ) ) ) text
  from  plsql_profiler_lines_cross_run p1,
        plsql_profiler_grand_total p4
where (p1.total_time >= p4.grand_total/100)
order by p1.total_time desc;
execute prof_report_utilities.rollup_all_runs;
prompt =
prompt =
prompt ====================
prompt  Number of lines actually executed in different units (by unit_name)
select p1.unit_owner,
       p1.unit_name,
       count( decode( p1.total_occur, 0, null, 0))  as lines_executed ,
       count(p1.line#) as lines_present,
       count( decode( p1.total_occur, 0, null, 0))/count(p1.line#) *100
                                       as pct
  from plsql_profiler_lines_cross_run p1
where (p1.unit_type in ( 'PACKAGE BODY', 'TYPE BODY',
                          'PROCEDURE', 'FUNCTION' )  )
group by p1.unit_owner, p1.unit_name;

prompt =
prompt =
prompt ====================
prompt  Number of lines actually executed for all units
select count(p1.line#) as lines_executed
  from plsql_profiler_lines_cross_run p1
where (p1.unit_type in ( 'PACKAGE BODY', 'TYPE BODY',
                          'PROCEDURE', 'FUNCTION' )  )
    AND p1.total_occur > 0;

prompt =
prompt =
prompt ====================
prompt  Total number of lines in all units
select count(p1.line#) as lines_present
  from plsql_profiler_lines_cross_run p1
where (p1.unit_type in ( 'PACKAGE BODY', 'TYPE BODY',
                          'PROCEDURE', 'FUNCTION' )  );
spool off
set termout on
edit profsum.out
set linesize 131
Oracle自带的profsum.sql产生的结果示例

 


已更新2行。

PL/SQL 过程已成功完成。

GRAND_TOTA
----------
   1560.57

  RUNID RUN_COMMENT    SECONDS
------- ----------- ----------
      1 no mod      643.964701
      2 mod          1158.1919

  RUNID RUN_COMMENT UNIT_OWNER  UNIT_NAME      SECONDS   PERCEN
------- ----------- ----------- -------------- --------- ------
      1 no mod      SCOTT       NO_MOD            506.44   78.6
      2 mod         SCOTT       DO_MOD           1054.13   91.0

UNIT_OWNER  UNIT_NAME      SECONDS   PERCENTAG
----------- -------------- --------- ---------
SCOTT       DO_MOD           1054.13     67.55
SCOTT       NO_MOD            506.44     32.45

未选定行

未选定行

SECONDS  UNIT_OWNER  UNIT_NAME       LINE# TEXT
-------- ----------- -------------- ------ ---------------------
   709.7 SCOTT       DO_MOD              8 if ( mod(cnt,1000) =
                                           0 )
   171.4 SCOTT       NO_MOD              8 if ( cnt = 1000 )
   160.3 SCOTT       NO_MOD              7 cnt := cnt + 1;
   158.5 SCOTT       DO_MOD              5 for i in 1 .. 500000
   155.0 SCOTT       NO_MOD              5 for i in 1 .. 500000
   147.3 SCOTT       DO_MOD              7 cnt := cnt + 1;
    38.6 SCOTT       DO_MOD             10 commit;
    19.4 SCOTT       NO_MOD             10 commit;
已选择8行。

PL/SQL 过程已成功完成。

未选定行

未选定行

LINES_EXECUTED
--------------
             0

LINES_PRESENT
-------------
            0
=================================trace info=================================
===========================Results for run #1 made on 24-7月 -06 17:04:39 =========================
(no mod) Run total time:    643.96 seconds
Unit #1: SCOTT.NO_MOD - Total time:    506.44 seconds
1                                                procedure no_mod as
2           0   0                                    cnt number := 0;
3                                                begin
4           0   0                                    dbms_profiler.start_profiler( 'no mod' );
5     500,001   154.96648  .00030993                 for i in 1 .. 500000
6                                                    loop
7     500,000   160.32336  .00032064                     cnt := cnt + 1;
8     500,000   171.38172  .00034276                     if ( cnt = 1000 )
9                                                        then
10         500   19.431397  .03886279                         commit;
11         500   .33597007  .00067194                         cnt := 0;
12                                                        end if;
13                                                    end loop;
14           1   .0034496  .0034496                   dbms_profiler.stop_profiler;
15                                                end;
===========================Results for run #2 made on 24-7月 -06 17:04:50 =========================
(mod) Run total time:   1158.19 seconds
Unit #1: SCOTT.DO_MOD - Total time:   1054.13 seconds
1                                                procedure do_mod as
2           0   0                                    cnt number := 0;
3                                                begin
4           0   0                                    dbms_profiler.start_profiler( 'mod' );
5     500,001   158.52169  .00031704                 for i in 1 .. 500000
6                                                    loop
7     500,000   147.34272  .00029468                     cnt := cnt + 1;
8     500,000   709.65247  .00141930                     if ( mod(cnt,1000) = 0 )
9                                                        then
10         500   38.609054  .07721810                         commit;
11                                                        end if;
12                                                    end loop;
13           1   .00322387  .00322387                 dbms_profiler.stop_profiler;
14                                                end;
============================================================================
PL/SQL 过程已成功完成。
================== Profiler report - all runs rolled up ===================
Unit SCOTT.DO_MOD:
1                                                procedure do_mod as
2           0   0                                    cnt number := 0;
3                                                begin
4           0   0                                    dbms_profiler.start_profiler( 'mod' );
5     500,001   158.52169  .00031704                 for i in 1 .. 500000
6                                                    loop
7     500,000   147.34272  .00029468                     cnt := cnt + 1;
8     500,000   709.65247  .00141930                     if ( mod(cnt,1000) = 0 )
9                                                        then
10         500   38.609054  .07721810                         commit;
11                                                        end if;
12                                                    end loop;
13           1   .00322387  .00322387                 dbms_profiler.stop_profiler;
14                                                end;
Unit SCOTT.NO_MOD:
1                                                procedure no_mod as
2           0   0                                    cnt number := 0;
3                                                begin
4           0   0                                    dbms_profiler.start_profiler( 'no mod' );
5     500,001   154.96648  .00030993                 for i in 1 .. 500000
6                                                    loop
7     500,000   160.32336  .00032064                     cnt := cnt + 1;
8     500,000   171.38172  .00034276                     if ( cnt = 1000 )
9                                                        then
10         500   19.431397  .03886279                         commit;
11         500   .33597007  .00067194                         cnt := 0;
12                                                        end if;
13                                                    end loop;
14           1   .0034496  .0034496                   dbms_profiler.stop_profiler;
15                                                end;
============================================================================
PL/SQL 过程已成功完成。
  用Tom的profsum.sql脚本产生的结果示例

 


已更新2行。

PL/SQL 过程已成功完成。
=
=
====================
Total time
GRAND_TOTAL
-----------
    1560.57
=
=
====================
Total time spent on each run
  RUNID RUN_COMMENT      SECS
------- ----------- ---------
      1 no mod         506.44
      2 mod           1054.13
=
=
====================
Percentage of time in each module, for each run separately
  RUNID RUN_COMMENT UNIT_OWNER  UNIT_NAME           SECS PERCEN
------- ----------- ----------- -------------- --------- ------
      1 no mod      SCOTT       NO_MOD            506.44  100.0
      2 mod         SCOTT       DO_MOD           1054.13  100.0
=
=
====================
Percentage of time in each module, summarized across runs
UNIT_OWNER  UNIT_NAME           SECS PERCENTAG
----------- -------------- --------- ---------
SCOTT       DO_MOD           1054.13     67.55
SCOTT       NO_MOD            506.44     32.45
=
=
====================
Lines taking more than 1% of the total time, each run separate
  RUNID     HSECS     PCT OWNER       UNIT_NAME       LINE# TEXT
------- --------- ------- ----------- -------------- ------ ---------------------
      2  70965.25    45.5 SCOTT       DO_MOD              8 if ( mod(cnt,1000) =
                                                            0 )
      1  17138.17    11.0 SCOTT       NO_MOD              8 if ( cnt = 1000 )
      1  16032.34    10.3 SCOTT       NO_MOD              7 cnt := cnt + 1;
      2  15852.17    10.2 SCOTT       DO_MOD              5 for i in 1 .. 500000
      1  15496.65     9.9 SCOTT       NO_MOD              5 for i in 1 .. 500000
      2  14734.27     9.4 SCOTT       DO_MOD              7 cnt := cnt + 1;
      2   3860.91     2.5 SCOTT       DO_MOD             10 commit;
      1   1943.14     1.2 SCOTT       NO_MOD             10 commit;
已选择8行。
=
=
====================
Most popular lines (more than 1%), summarize across all runs
    HSECS     PCT UNIT_OWNER  UNIT_NAME       LINE# TEXT
--------- ------- ----------- -------------- ------ ---------------------
70965.25    45.5 SCOTT       DO_MOD              8 if ( mod(cnt,1000) =
                                                    0 )
17138.17    11.0 SCOTT       NO_MOD              8 if ( cnt = 1000 )
16032.34    10.3 SCOTT       NO_MOD              7 cnt := cnt + 1;
15852.17    10.2 SCOTT       DO_MOD              5 for i in 1 .. 500000
15496.65     9.9 SCOTT       NO_MOD              5 for i in 1 .. 500000
14734.27     9.4 SCOTT       DO_MOD              7 cnt := cnt + 1;
  3860.91     2.5 SCOTT       DO_MOD             10 commit;
  1943.14     1.2 SCOTT       NO_MOD             10 commit;
已选择8行。

PL/SQL 过程已成功完成。
=
=
====================
Number of lines actually executed in different units (by unit_name)
UNIT_OWNER  UNIT_NAME      LINES_EXECUTED LINES_PRESENT     PCT
----------- -------------- -------------- ------------- -------
SCOTT       DO_MOD                      5             7    71.4
SCOTT       NO_MOD                      6             8    75.0
=
=
====================
Number of lines actually executed for all units
LINES_EXECUTED
--------------
            11
=
=
====================
Total number of lines in all units
LINES_PRESENT
-------------
           15

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/20542911/viewspace-615712/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/20542911/viewspace-615712/

你可能感兴趣的:(Oracle数据库中使用DBMS_PROFILER进行调优)