使用DBMS_PROFILER进行PL/SQL性能分析

可以使用DBMS_PROFILER进行PL/SQL性能分析,或者进行覆盖性分析。测试如下:


创建存储数据所需表:
?/rdbms/admin/PROFTAB.SQL,在收集信息的用户下执行,创建所需表和存储过程.
或者?/rdbms/admin/PROFLOAD.SQL,在系统用户下执行,创建所需表和存储过程,并将SELECT/INSERT/UPDATE权限授予所有用户,并创建同义词。


权限:
需要有create权限才能收集对象信息的,只有execute权限是不能收集对象信息的;
被分析对象是否需要debug方式编译?不需要,但建议;这样可以获取额外信息.

--测试数据库版本:
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

1,分析简单存储过程

1.1创建测试表
drop table p;
create table p
as
select object_id as id from dba_objects where object_id is not null;

alter table p
  add constraint pk_p primary key(id);

drop table c;
create table c
as
select object_id as id from dba_objects where object_id is not null and rownum<500;

alter table c
  add constraint fk_c_r_p foreign key(id) references p(id) on delete cascade;


create or replace procedure prc_del
is
begin
  for x in 1..1000 loop
    delete from p where id=x;
  end loop;
  commit;
end;
/

1.2 开始分析
exec dbms_profiler.start_profiler;
SQL> exec dbms_profiler.start_profiler;
BEGIN dbms_profiler.start_profiler; END;

*
ERROR at line 1:
ORA-06528: Error executing PL/SQL profiler
ORA-06512: at "SYS.DBMS_PROFILER", line 123
ORA-06512: at "SYS.DBMS_PROFILER", line 132
ORA-06512: at line 1

==〉奇怪的错误代码

SQL> @?/rdbms/admin/proftab.sql


exec dbms_profiler.start_profiler;

exec prc_del;

--exec dbms_profiler.flush_data;

exec dbms_profiler.stop_profiler;

1.3分析结果查询
SQL> select runid,run_total_time from mh.plsql_profiler_runs;

     RUNID RUN_TOTAL_TIME
---------- --------------
         1     1.7716E+11

1 row selected.

SQL> set linesize 200
SQL> r
  1  select u.runid, unit_number, unit_type, unit_name
  2    from mh.plsql_profiler_runs r, mh.plsql_profiler_units u
  3*  where r.runid = u.runid

     RUNID UNIT_NUMBER UNIT_TYPE                        UNIT_NAME
---------- ----------- -------------------------------- --------------------------------
         1           1 ANONYMOUS BLOCK                 
         1           2 ANONYMOUS BLOCK                 
         1           3 PROCEDURE                        PRC_DEL
         1           4 ANONYMOUS BLOCK                 
         1           5 ANONYMOUS BLOCK                 

5 rows selected.


col line# for 999
col total_occur for 9999999
col total_time for 99999999999
col min_time for 99999999999
col max_time for 99999999999
col text for a40
select d.line# , d.total_occur , d.total_time ,
       d.min_time, d.max_time , s.text
  from mh.plsql_profiler_units u, mh.plsql_profiler_data d, all_source s
 where u.runid = u.runid
   and u.unit_number = d.unit_number
   and s.owner = u.unit_owner
   and s.name = u.unit_name
   and s.TYPE = u.unit_type
   and s.line = d.line#;
LINE# TOTAL_OCCUR   TOTAL_TIME     MIN_TIME     MAX_TIME TEXT
----- ----------- ------------ ------------ ------------ ----------------------------------------
    1           0         9000         4000         5000 procedure prc_del
    4        1003      1001000         1000         4000   for x in 1..1000 loop
    5        1002    296954000        60000     18913000     delete from p where id=x;
    7           1       221000       221000       221000   commit;
    8           1         5000         5000         5000 end;

5 rows selected.

1.4重新创建测试表,获取测试数据如下:
select d.line# , d.total_occur , d.total_time ,
       d.min_time, d.max_time , s.text
  from mh.plsql_profiler_units u, mh.plsql_profiler_data d, all_source s
 where u.runid = u.runid
   and u.unit_number = d.unit_number
   and s.owner = u.unit_owner
   and s.name = u.unit_name
   and s.TYPE = u.unit_type
   and s.line = d.line#
   and u.runid=2
   and u.runid=d.runid;
LINE# TOTAL_OCCUR   TOTAL_TIME     MIN_TIME     MAX_TIME TEXT
----- ----------- ------------ ------------ ------------ ----------------------------------------
    1           0        19000        19000        19000 procedure prc_del
    4        1001      1082000         1000        70000   for x in 1..1000 loop
    5        1000    247706000        59000     10843000     delete from p where id=x;
    7           1       207000       207000       207000   commit;
    8           1         6000         6000         6000 end;

5 rows selected.

1.5 重新创建测试表,子表创建索引,获取测试数据如下:
create index idx_c_id;

select d.line# , d.total_occur , d.total_time ,
       d.min_time, d.max_time , s.text
  from mh.plsql_profiler_units u, mh.plsql_profiler_data d, all_source s
 where u.runid = u.runid
   and u.unit_number = d.unit_number
   and s.owner = u.unit_owner
   and s.name = u.unit_name
   and s.TYPE = u.unit_type
   and s.line = d.line#
   and u.runid=3
   and u.runid=d.runid;
LINE# TOTAL_OCCUR   TOTAL_TIME     MIN_TIME     MAX_TIME TEXT
----- ----------- ------------ ------------ ------------ ----------------------------------------
    1           0         5000         5000         5000 procedure prc_del
    4        1001       989000         1000        16000   for x in 1..1000 loop
    5        1000    526245000        58000    283551000     delete from p where id=x;
    7           1       207000       207000       207000   commit;
    8           1         7000         7000         7000 end;

5 rows selected.

==>外键创建了索引,虽然加快了查询速度,但由于级联删除,导致所耗时间增加。


2,分析有调用关系的存储过程
2.1 创建测试用存储过程
create or replace function prc_a(x int,y int) return int
is
begin
   return x+y;
end;
/


create or replace function prc_b(x int,y int) return int
is
begin
   return prc_a(x,y);
end;
/

2.2 收集信息
exec dbms_profiler.start_profiler;

set serveroutput on
declare
  s int;
begin
  for x in 1..100 loop
     s := prc_b(x,s);
  end loop;
  dbms_output.put_line('==>'||s);
end;
/

exec dbms_profiler.stop_profiler;


2.3 查询结果
col unit_name for a15
col line# for 999
col total_occur for 9999999
col total_time for 99999999999
col min_time for 99999999999
col max_time for 99999999999
col text for a40
select u.unit_name,d.line# , d.total_occur , d.total_time ,
       d.min_time, d.max_time , s.text
  from mh.plsql_profiler_units u, mh.plsql_profiler_data d, all_source s
 where u.runid = u.runid
   and u.unit_number = d.unit_number
   and s.owner = u.unit_owner
   and s.name = u.unit_name
   and s.TYPE = u.unit_type
   and s.line = d.line#
   and u.runid=5
   and u.runid=d.runid;
UNIT_NAME       LINE# TOTAL_OCCUR   TOTAL_TIME     MIN_TIME     MAX_TIME TEXT
--------------- ----- ----------- ------------ ------------ ------------ ----------------------------------------
PRC_B               1           0       107000         1000         3000 function prc_b(x int,y int) return int
PRC_B               4         100       196000         1000        17000    return prc_a(x,y);
PRC_B               5         100        85000         1000         1000 end;
PRC_A               1           0       106000         1000         3000 function prc_a(x int,y int) return int
PRC_A               4         100        88000         1000         1000    return x+y;
PRC_A               5         100        92000         1000         2000 end;

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

转载于:http://blog.itpub.net/18922393/viewspace-755276/

你可能感兴趣的:(使用DBMS_PROFILER进行PL/SQL性能分析)