dbms_profiler用来测试PL/SQL代码非常有用,比如找出哪一段代码比较耗时,也可以用来比较不同算法之间的差异。也得到了一些第三方工具的支持,如PLSQL DEVELOPER。
来源:http://hi.baidu.com/edeed/blog/item/345401e9a8851d38b80e2db4.html
1、安装 1.1、以sys用户创建dbms_profiler包 SQL> conn /as sysdba SQL> desc dbms_profiler --先确信dbms_profiler包是否存在,如果不存在则通过下面的方式创建 SQL> @?/rdbms/admin/profload.sql 包主要使用的函数是: start_profiler --启动 profiler stop_profiler --停止 profiler 1.2、创建一个用于存放跟踪信息的用户,及其prof表和序列的同义词 SQL> CREATE USER profiler IDENTIFIED BY iamwangnc; SQL> grant connect,resource to profiler; SQL> CREATE PUBLIC SYNONYM plsql_profiler_runs FOR profiler.plsql_profiler_runs; SQL> CREATE PUBLIC SYNONYM plsql_profiler_units FOR profiler.plsql_profiler_units; SQL> CREATE PUBLIC SYNONYM plsql_profiler_data FOR profiler.plsql_profiler_data; SQL> CREATE PUBLIC SYNONYM plsql_profiler_runnumber FOR profiler.plsql_profiler_runnumber; 1.3、用profiler用户创建prof表和序列,并赋权 SQL> conn profiler/iamwangnc SQL> @?/rdbms/admin/proftab.sql SQL> GRANT SELECT ON plsql_profiler_runnumber TO PUBLIC; SQL> GRANT SELECT,INSERT,UPDATE,DELETE ON plsql_profiler_data TO PUBLIC; SQL> GRANT SELECT,INSERT,UPDATE,DELETE ON plsql_profiler_units TO PUBLIC; SQL> GRANT SELECT,INSERT,UPDATE,DELETE ON plsql_profiler_runs TO PUBLIC; 备注: plsql_profiler_runs --prof运行信息 plsql_profiler_units --prof每个单元信息 plsql_profiler_data --prof每个单元的详细数据 plsql_profiler_runnumber --用来生成prof唯一运行编号的序列 2、应用实例 SQL> conn u_test/iamwangnc SQL> create table tab_test (a int); SQL> CREATE OR REPLACE PROCEDURE sp_test AS BEGIN FOR I IN 1 .. 100 LOOP INSERT INTO tab_test VALUES (I); END LOOP; COMMIT; END; / SQL> set serverout on SQL> DECLARE v_run_number integer; v_temp1 integer; BEGIN --启动profiler sys.DBMS_PROFILER.start_profiler (run_number => v_run_number); --显示当前跟踪的运行序号(后面查询要用) DBMS_OUTPUT.put_line ('run_number:' || v_run_number); --运行要跟踪的PLSQL sp_test; --停止profiler sys.DBMS_PROFILER.stop_profiler; END; / run_number:1 记住输出的运行号。 3、查询结果 SQL> set lines 256 pages 100 获得本次prof的基本运行信息: SQL> select runid,run_owner,run_date,run_total_time from plsql_profiler_runs; RUNID RUN_OWNER RUN_DATE RUN_TOTAL_TIME ---------- -------------------------------- ------------------- -------------- 1 U_TEST 2008-11-26.17:18:39 54215000 根据运行号和单元名(即测试的存储过程名)获得本次prof的单元信息: SQL> select unit_number,unit_type,unit_owner,unit_name,unit_timestamp,total_time from plsql_profiler_units where runid = 1 and unit_name = 'SP_TEST'; UNIT_NUMBER UNIT_TYPE UNIT_OWNER UNIT_NAME UNIT_TIMESTAMP TOTAL_TIME ----------- -------------------------------- -------------------------------- -------------------------------- ------------------- ---------- 2 PROCEDURE U_TEST SP_TEST 2008-11-26.17:17:56 0 根据运行号和单元号获得该存储过程每行运行的统计信息: SQL> select runid,unit_number,line#,total_occur,total_time,min_time,max_time from plsql_profiler_data where runid = 1 and unit_number = 2; RUNID UNIT_NUMBER LINE# TOTAL_OCCUR TOTAL_TIME MIN_TIME MAX_TIME ---------- ----------- ---------- ----------- ---------- ---------- ---------- 1 2 1 0 3000 3000 3000 1 2 4 101 179000 1000 3000 1 2 6 100 7084000 17000 1141000 1 2 9 1 336000 336000 336000 1 2 10 1 2000 2000 2000 以上信息都不怎么直观,通过下面的sql更加直观展示: SQL> col text format a60 SQL> SELECT d.line#, --代码行号 s.text, --源代码 d.total_time, --总共运行时间(单位10000亿分之一秒) d.total_occur, --总共运行次数 d.min_time, --最小运行时间 d.max_time --最大运行时间 FROM plsql_profiler_data d, sys.all_source s, plsql_profiler_units u WHERE d.runid = 1 --运行号 and u.unit_name = 'SP_TEST' --单元名,即被测试的存储过程名 AND u.runid = d.runid AND d.unit_number = u.unit_number AND d.total_occur <> 0 AND s.TYPE(+) = u.unit_type AND s.owner(+) = u.unit_owner AND s.name(+) = u.unit_name AND d.line# = NVL (s.line, d.line#) ORDER BY u.unit_number, d.line#; LINE# TEXT TOTAL_TIME TOTAL_OCCUR MIN_TIME MAX_TIME ---------- ------------------------------------------------------------ ---------- ----------- ---------- ---------- 4 FOR I IN 1 .. 100 179000 101 1000 3000 6 INSERT INTO tab_test 7084000 100 17000 1141000 9 COMMIT; 336000 1 336000 336000 10 END; 2000 1 2000 2000 4、使用metalink里提供的profiler.sql脚本生成超文本测试结果信息 profiler.sql文件参见metalink的Note:243755.1 。 知道运行号的情况下: SQL> @profiler.sql 1 或者不输入运行号: SQL> @profiler 然后选择并输入运行号。 会在当前目录下生成一份名叫profiler_<runid>.html的超文本文件,很直观,如下: ![]() 以上介绍的是通过手工方法应用Profiler,使用相对比较烦杂,下面将详细介绍在PLSQL DEVELOPER 应用Profiler。 5.1、打开test window 方法一、新建一个test window,在test window中输入你要执行的PLSQL脚本。 方法二、选择要跟踪运行的存储过程,右键快捷菜单选择Test,如果是Package那么先右键快捷菜单里选择View,在打开的Package的存储过程列表里右键快捷菜单选择Test,如下图所示: ![]() 5.2、进入调试窗口,在1处单击,打开profiler开关,在2处单击或按F8执行 ![]() ![]() 每列的详细意义如下: unit --单元名称,即执行的存储过程,包括其调用的过程 line --代码行号 total time --此行执行时间(颜色长度表示本行代码的执行时间与最长代码执行时间的百分比图) occurrences --此行执行次数 text --对应代码行,对于加密的代码,将不能显示 Average time —平均运行时间 maximum time --最大运行时间 minimum time --最小运行时间(以上三个时间默认不显示,可以通过配置对话框选择显示,参加4.4) 列表中显示的源代码只显示一行,如果要定位则可以在对应的行中打开右键,选择[Go to unit line] ,这样就会直接跳到对应的源代码位置。 Profiler面板的工具栏说明: a、显示配置对话框 b、刷新 c、删除当前运行号的数据 d、Run 显示当前的系统的所有Profiler列表,缺省为当前的跟踪 e、Unit 显示本次跟踪的单元列表信息(执行时间),缺省为所有单元的执行时间 5.4、Profiler配置对话框 ![]() Available Columns --可用列 Selected Columns --选择要查看的列 Time units --时间单位(秒、毫秒、微秒) Show 0 occurrences --是否显示执行0次的处理语句 Graphical time display --用图形显示处理时间的颜色深度百分比 --End-- |