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