Oracle’s DBMS_Profiler:PL/SQL 性能调整


Oracle’s DBMS_Profiler:PL/SQL 性能调整

DBMS_PROFILER 包举例

下面是我提供的怎样使用配置的简单例子,运行配置文件来测试下面例程的性能. 例程用到的自定义脚本紧随其后.

1. 创建过程.

create or replace procedure am_perf_chk (pi_seq in number,

pio_status in out nocopy varchar2) is

l_dat date := sysdate;

begin

if trunc(l_dat) = '21-sep-02' and pi_seq = 1 then

pio_status := 'OK';

else

pio_status := 'Invalid tape loaded';

end if;

exception

when others then

pio_status := 'Error in am_perf_chek';

end;

2. 用配置文件调用例程

替换上面的例程, 执行call_profiler.sql脚本(脚本代码参见下面),传入pi_seq=2

SQL> @d:\am\call_profiler.sql

Profiler started

Invalid tape loaded

PL/SQL procedure successfully completed.

Profiler stopped

Profiler flushed

runid:8

3. 评估执行时间:
执行eavluate_profiler_results.sql脚本,得到时间统计

SQL> @d:\am\evaluate_profiler_results.sql

Enter value for runid: 8

Enter value for name: am_perf_chk

Enter value for owner: scott

Line Occur Msec Text

---------- ---------- ---------- -------------------------------------------------------------------

1 procedure am_perf_chk (pi_seq in number,

2 pio_status in out nocopy varchar2) is

3 2 43.05965 l_dat date := sysdate;

4 begin

5 1 86.35732 if trunc(l_dat) = '21-sep-02' and pi_seq = 1 then

6 0 0 pio_status := 'OK';

7 else

8 1 8.416151 pio_status := 'Invalid tape loaded';

9 end if;

10 exception

11 when others then

12 0 0 pio_status := 'Error in am_perf_chek';!

13 1 2.410361 end;

13 rows selected.

Code% coverage

--------------

66.6666667

4. 正如你看到的,第三行执行时间提高到86毫秒.但是改变if语句,重新执行上面的过程,将会得到新的结果:

Line Occur Msec Text

---------- ---------- ---------- -------------------------------------------------------------------

1 procedure am_perf_chk (pi_seq in number,

2 pio_status in out nocopy varchar2) is

3 2 17.978816 l_dat date := sysdate;

4 begin

5 1 8.419503 if pi_seq = 1 and trunc(l_dat) = '21-sep-02' then

6 0 0 pio_status := 'OK';

7 else

8 1 7.512684 pio_status := 'Invalid tape loaded';

9 end if;

10 exception

11 when others then

12 0 0 pio_status := 'Error in !am_perf_chek';

13 1 .731657 end;

13 rows selected.

Code% coverage

--------------

66.6666667

5. 正如你看到的, 这种情境下第三行执行时间从86毫秒减少到8毫秒,多余的时间是由于内置trunc()函数引起., 这种情境下如果第一个条件为false,则不会执行trunc()函数.这仅仅是个简单的例子,当你测试的例程越大,你面临的挑战更大.

这个配置结果也证明了执行期间代码被覆盖多少行,从而让我们知道处于性能监视中的代码范围。如果任何PL/SQL块性能出现问题,它也能提炼出各种不同情景的正在在执行的代码并检查配置结果,从而查明问题所在。

6. 对于一个特定的情景,如果执行一段特殊的代码段,可以得到合理的分析,即使代码根本一点都不能运行。

环境的创建

默认安装或数据库的创建状态下,DBMS_PROFILER包不会自动安装,请DBA用profload.sql脚本创建它.用一个权限较大的或一个单独的用户,创建存储统计信息的表。如果

用如SYS用户创建,则给其它用户授予DML权限,并且对这些表创建一个共同的简写名.

创建表的如下:

PLSQL_PROFILER_RUNS表:PL/SQL配置的运行细节.

PLSQL_PROFILER_UNITS表:运行中每一个库单元的信息.

PLSQL_PROFILER_DATA表:所有配置文件运行时的数据累积.

PLSQL_PROFILER_RUNNUMBER序列提供了RUNID

运行和解释配置数据

ORACLE提供了三个表来统计,填充RUNID。有许多第三方的工具可以提供自定义的基于这些数据的报告,ORACLE提供profrep.sql脚本评估数据(在

  1<oracle_home>\plsql\demo\目录下),下面的两个简单脚本就是上面用到的,用来检查程序单元的执行时间.执行时间以毫秒存储   
  2  
  3\-----------------------------------------------------------   
  4  
  5Script: call_profiler.sql   
  6  
  7\-----------------------------------------------------------   
  8  
  9set head off   
 10  
 11set pages 0   
 12  
 13select decode(dbms_profiler.start_profiler, '0', 'Profiler started', 'Profiler error')   
 14  
 15from dual;   
 16  
 17  
 18  
 19\--&lt; place your routine in the below block &gt;\--   
 20  
 21declare   
 22  
 23l_status varchar2(200);   
 24  
 25begin   
 26  
 27am_perf_chk(2, l_status);   
 28  
 29dbms_output.put_line(l_status);   
 30  
 31end;   
 32  
 33/   
 34  
 35  
 36  
 37select decode(dbms_profiler.stop_profiler, '0', 'Profiler stopped', 'Profiler error')   
 38  
 39from dual;   
 40  
 41select decode(dbms_profiler.flush_data, '0', 'Profiler flushed', 'Profiler error')   
 42  
 43from dual;   
 44  
 45select 'runid:' || plsql_profiler_runnumber.currval   
 46  
 47from dual;   
 48  
 49set head on   
 50  
 51set pages 200   
 52  
 53  
 54  
 55\-----------------------------------------------------------   
 56  
 57Script: evaluate_profiler_results.sql   
 58  
 59\-----------------------------------------------------------   
 60  
 61undef runid   
 62  
 63undef owner   
 64  
 65undef name   
 66  
 67set verify off   
 68  
 69select s.line "Line", p.total_occur "Occur", p.total_time "Msec", s.text "Text"   
 70  
 71from all_source s, (select u.unit_owner, u.unit_name, u.unit_type, d.line#,   
 72  
 73d.total_occur, d.total_time/1000000 total_time   
 74  
 75from plsql_profiler_data d, plsql_profiler_units u   
 76  
 77where u.runid = &amp;&amp;runid   
 78  
 79and u.runid = d.runid   
 80  
 81and u.unit_number = d.unit_number) p   
 82  
 83where s.owner = p.unit_owner (+)   
 84  
 85and s.name = p.unit_name (+)   
 86  
 87and s.type = p.unit_type (+)   
 88  
 89and s.line = p.line# (+)   
 90  
 91and s.name = upper('&amp;&amp;name')   
 92  
 93and s.owner = upper('&amp;&amp;owner')   
 94  
 95order by s.line;   
 96  
 97select exec.cnt/total.cnt * 100 "Code% coverage"   
 98  
 99from (select count(1) cnt   
100  
101from plsql_profiler_data d, plsql_profiler_units u   
102  
103where d.runid = &amp;&amp;runid   
104  
105and u.runid = d.runid   
106  
107and u.unit_number = d.unit_number   
108  
109and u.unit_name = upper('&amp;&amp;name')   
110  
111and u.unit_owner = upper('&amp;&amp;owner')) total,   
112  
113(select count(1) cnt   
114  
115from plsql_profiler_data d, plsql_profiler_units u   
116  
117where d.runid = &amp;&amp;runid   
118  
119and u.runid = d.runid   
120  
121and u.unit_number = d.unit_number   
122  
123and u.unit_name = upper('&amp;&amp;name')   
124  
125and u.unit_owner = upper('&amp;&amp;owner')   
126  
127and d.total_occur &gt; 0) exec;   
128  
129undef runid   
130  
131undef owner   
132  
133undef name   
134  
135  
136  
137结论   
138  
139DBMS_PROFILER是非常强大的工具,其一就是可以识别PL/SQL的性能问题.这个工具最好用在开发时期,用来调整基于各种应用的情景的代码,它也能用很好的调整已在使用中的例程并且采取显而易见的时间去执行。总之,这个工具可以给每一行代码给予性能统计,它可以帮助我们评估和调整到一个出色的水平,当检查SQL语句的性能问题时,PL/SQL代码不应该忽略,相反应该调整到最佳的结果.</oracle_home>
Published At
Categories with 数据库类
comments powered by Disqus