`

Oracle's DBMS_PROFILER: PL/SQL Performance Tuning

 
阅读更多

By Amar Kumar Padhi

<!--content_start-->

An application can always be fine-tuned for better performance with the use of better alternatives or with the new features introduced with every release of Oracle.

Simply inspecting the code can bring out the bottlenecks eating up your processing time. Using explain plan to fine tune the SQL statements resolves issues most of the time. However, sometimes it may not be that simple. It is baffling when all the SQL statements are well tuned but the routine still takes noticeable time to execute.

DBMS_PROFILER Package
Oracle 8i provides a new tool called PL/SQL Profiler. This is a powerful tool to analyze a Program unit execution and determine the runtime behavior. The results generated can then be evaluated to find out the hot areas in the code. This tool helps us identify performance bottlenecks, as well as where excess execution time is being spent in the code. The time spent in executing an SQL statement is also generated. This process is implemented with DBMS_PROFILER package.

The possible profiler statistics that are generated:
   1. Total number of times each line was executed.
   2. Time spent executing each line. This includes SQL statements.
   3. Minimum and maximum duration spent on a specific line of code.
   4. Code that is actually being executed for a given scenario.

DBMS_PROFILER.START_PROFILER
The DBMS_PROFILER.START_PROFILER tells Oracle to start the monitoring process. An identifier needs to be provided with each run that is used later to retrieve the statistics.

e.g.: 
l_runstatus := dbms_profiler.start_profiler('am' || 
to_char(sysdate)); 

DBMS_PROFILER.STOP_PROFILER
The DBMS_PROFILER.STOP_PROFILER tells Oracle to stop the monitoring.

e.g.: 
l_runstatus := dbms_profiler.stop_profiler; 

DBMS_PROFILER.FLUSH_DATA
The data collected for an execution is held in the memory. Calling the DBMS_PROFILER.FLUSH_DATA routine tells Oracle to save this data in profiler tables and clear the memory.

e.g.: 
l_runstatus := dbms_profiler.flush_data; 

The above functions return the following status'.
   0 : Successful completion
   1 : Incorrect parameters passed (error_parm).
   2 : data flush operation failed (error_io).
   -1 : mismatch between package and database implementation (error_version).

 

 

EXAMPLE on using DBMS_PROFILER
This is a simple example that I am providing just as a reference on how to use the Profiler. I will run profiler and debug the following routine for performance. Customized scripts that are used in the example can be found at the end of this article.

1. Creating my procedure.

E.g.: 
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. Calling the routine with profiler.
The above routine will be placed and called in the call_profiler.sql (script details given below). The pi_seq value is passed as 2.

	SQL> @d:\am\call_profiler.sql 
	Profiler started 
	Invalid tape loaded 
	PL/SQL procedure successfully completed. 
	Profiler stopped 
	Profiler flushed 
	runid:8 

3. Evaluating the execution time.
The evalute_profiler_results.sql is called to get the time statistics.

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

As you can see, line 3 shows execution time as 86 msec which can be improved on. The if statement is altered (if pi_seq = 1 and trunc(l_dat) = '21-sep-02' then) and the above process is repeated. The following is the new result:

      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

As you can see, line 3 execution time is reduced from 86 msec to 8 msec for the tested scenario. The excess time was taken due to the trunc() built-in. Shifting this to the right prevents its execution if the first condition is false. This is a small example and you will be thrown more challenges when debugging bigger routines.

The profiler result also shows how much of the code was covered during execution. This would give us an idea of the extent of the code that was performance monitored. The idea is to try out various scenarios for executing the code and check on the profiler results to find out if any PL/SQL performance issues are encountered.

Logical analysis can be carried out if a particular piece of code is executed for a given scenario, when it should not be executing at all.

 

 

Creation of the environment
The DBMS_PROFILER package is not automatically created during default installation or creation of the database. Ask the DBA to create the package using the profload.sql script. Create tables for storing statistics either in one central user or in each individual user, using proftab.sql. If tables are created in one central user, like SYS, then grant DML privileges to all other users. Create public synonym on the tables with the same name.

The tables created are:
   PLSQL_PROFILER_RUNS: Run-specific information for the PL/SQL profiler
   PLSQL_PROFILER_UNITS: Information about each library unit in a run
   PLSQL_PROFILER_DATA: Accumulated data from all profiler runs.

A sequence PLSQL_PROFILER_RUNNUMBER provides the run id.

Running and Interpreting Profiler Data
Oracle provides three tables where statistics are populated for a run id. There are many third party tools available to provide customized reports based on this data. Oracle provides profrep.sql and profsum.sql to evaluate data (present in <oracle_home>\plsql\demo\). Below I have provided two simple scripts used in the examples above, to check instantly on a program unit execution time. The execution time is stored in milli-seconds.

-----------------------------------------------------------
Script: call_profiler.sql
-----------------------------------------------------------
set head off
set pages 0
select decode(dbms_profiler.start_profiler, '0', 'Profiler started', 'Profiler error')
from   dual;

--< place your routine in the below block >-- 
declare
  l_status varchar2(200);
begin
  am_perf_chk(2, l_status);
  dbms_output.put_line(l_status);
end;
/

select decode(dbms_profiler.stop_profiler, '0', 'Profiler stopped', 'Profiler error')
from   dual;
select decode(dbms_profiler.flush_data, '0', 'Profiler flushed', 'Profiler error')
from   dual;
select 'runid:' || plsql_profiler_runnumber.currval 
from   dual;
set head on
set pages 200

-----------------------------------------------------------
Script: evaluate_profiler_results.sql
-----------------------------------------------------------
undef runid
undef owner
undef name
set verify off
select s.line "Line", p.total_occur "Occur", p.total_time "Msec", s.text "Text"
from   all_source s, (select u.unit_owner, u.unit_name, u.unit_type, d.line#,
                             d.total_occur, d.total_time/1000000 total_time
                      from   plsql_profiler_data d, plsql_profiler_units u
                      where  u.runid = &&runid
                      and    u.runid = d.runid
                      and    u.unit_number = d.unit_number) p
where  s.owner = p.unit_owner (+)
and    s.name = p.unit_name (+)
and    s.type = p.unit_type (+)
and    s.line = p.line# (+)
and    s.name = upper('&&name')
and    s.owner = upper('&&owner')
order by s.line;
select exec.cnt/total.cnt * 100 "Code% coverage"
from  (select count(1) cnt
      from plsql_profiler_data d, plsql_profiler_units u
      where d.runid = &&runid
      and u.runid = d.runid
      and u.unit_number = d.unit_number
      and u.unit_name = upper('&&name')
      and u.unit_owner = upper('&&owner')) total,
     (select count(1) cnt
      from plsql_profiler_data d, plsql_profiler_units u
      where d.runid = &&runid
      and u.runid = d.runid
      and u.unit_number = d.unit_number
      and u.unit_name = upper('&&name')
      and u.unit_owner = upper('&&owner')
      and d.total_occur > 0) exec;
undef runid
undef owner
undef name

 

Conclusion
DBMS_PROFILER is a very powerful tool and the first of its kind to identify performance issues on the PL/SQL front. This utility can be best used in the development stages to fine tune code based on various applicable scenarios. It can also be used to fine tune routines that are already in production and are taking noticeable time to execute. Overall, this utility gives statistics for each line of code that will help us in evaluating and tuning at a finer level. Just as SQL statements are checked for performance, PL/SQL code should not be ignored but should be tuned for optimal results as well.

<!--content_stop--><!--content_stop-->
分享到:
评论

相关推荐

    Oracle PL/SQL常用47个工具包

    19. **DBMS_PROFILER**: 性能分析工具,追踪PL/SQL代码的执行时间。 20. **DBMS_METADATA_DIFF**: 比较并显示两个数据库对象之间的差异。 21. **DBMS_RLS**: 实现行级安全性,控制用户对特定行的访问。 22. **...

    oracle Database 11g :PL/SQL

    ### Oracle Database 11g: PL/SQL 基础 #### 一、概述 Oracle Database 11g 是 Oracle 公司推出的一款强大的数据库管理系统,它提供了多种新功能和改进来提高性能、可靠性和安全性。其中 PL/SQL(Procedural ...

    ORACLE SYS.DBMS_REGISTRY_SYS has errors

    标题中的问题“ORACLE SYS.DBMS_REGISTRY_SYS has errors”指的是在Oracle数据库系统中,系统包BODY `SYS.DBMS_REGISTRY_SYS` 出现错误,导致了一系列的PL/SQL调用失败。这种错误通常与数据库的元数据注册功能有关,...

    Oracle PL/SQL PRofiler应用指南

    ### Oracle PL/SQL Profiler应用指南 #### 一、简介 在Oracle数据库中,调试与性能优化是一项重要的工作。为了帮助开发人员和DBA更好地理解并优化PL/SQL代码的执行效率,Oracle提供了多种工具,其中之一就是PL/SQL...

    oracle pl/sql最佳实践

    4. **PL/SQL性能工具**:使用DBMS_PROFILER分析PL/SQL代码的性能瓶颈。通过DBMS_METADATA获取PL/SQL对象的源代码,便于代码审查和重构。 5. **输入验证**:对用户输入进行严格的检查,防止SQL注入和其他安全问题。...

    Oracle_PL/SQL编程

    Oracle PL/SQL编程是Oracle数据库系统中的一个核心组成部分,它扩展了SQL的语法,使得数据库管理及应用程序开发更具灵活性和可编程性。PL/SQL融合了SQL查询和控制流语句,提供了处理复杂业务逻辑的能力。 PL/SQL的...

    Oracle Database PL/SQL Packages and Types Reference 11g Release

    2. **内置PL/SQL包**:Oracle提供了一系列内置的PL/SQL包,如DBMS_OUTPUT用于调试输出,DBMS_ALERT用于异步通知,DBMS_PIPE用于进程间通信,DBMS_JOB和DBMS_SCHEDULER用于计划任务等。这些包极大地扩展了PL/SQL的...

    oracle 9i pl/sql程序设计笔记

    ### Oracle 9i PL/SQL程序设计笔记精要 #### PL/SQL基础知识概览 **标题与描述**:本文档围绕“Oracle 9i PL/SQL程序设计笔记”这一核心主题,深入探讨了PL/SQL语言的基础知识及其在Oracle 9i数据库环境中的应用。...

    pl/sql精通

    《PL/SQL精通》这本书是针对Oracle数据库管理系统中PL/SQL编程语言的深入学习指南。Oracle SQL是Oracle数据库系统的核心语言,而PL/SQL则扩展了SQL的功能,提供了过程化编程的能力,使得数据库管理和开发更加高效和...

    Re-post: DBMS_XPLAN : Display Oracle Execution Plans

    标题“DBMS_XPLAN: 显示Oracle执行计划”是一个关于Oracle数据库系统中用于分析SQL查询执行性能的重要工具的讨论。这个工具允许用户查看SQL语句的执行计划,从而理解数据库如何处理这些语句,以及哪些操作可能影响...

    Oracle PL/SQL学习官方教材

    Oracle PL/SQL是一种强大的编程语言,它将SQL与过程编程语言的特性相结合,为数据库开发提供了丰富的功能。在Oracle数据库环境中,PL/SQL是开发高效、可靠和可维护的数据库应用程序的关键工具。以下是对"Oracle PL/...

    oracle dbms_lob

    Oracle数据库系统中,`DBMS_LOB`是一个重要的PL/SQL包,专门用于处理大型对象(LOBs,Large Object)。LOBs是Oracle提供的一种数据类型,用于存储大量数据,如文本、图像、音频或视频文件等。这个包包含了各种过程和...

    Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(一)

    Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(一) http://download.csdn.net/source/3268267 Oracle 11g SQL和PL SQL从入门到精通 pdf格式电子书 下载(二) ...

    PL-SQL(chinese).rar_pl_pl sql_pl/sql

    PL/SQL,全称Procedural Language/Structured Query Language,是Oracle数据库的一种扩展,它集成了SQL语言的查询功能,并增加了过程式编程的元素,使得数据库管理与应用程序开发更为便捷高效。本文将深入探讨PL/SQL...

    oracle实验五 PL/SQL编程

    ### Oracle 实验五 PL/SQL编程 #### 实验目的 本次实验旨在使学习者深入了解PL/SQL编程的基础知识与实际应用。具体目标包括: 1. **掌握PL/SQL的数据类型和基本语法**:理解PL/SQL中不同数据类型的定义与使用方法...

    调整数据库时区版本脚本DBMS_DST_scriptsV1.9.zip

    通过此版本可以把oracle时区版本调整到为最新版本,一般配合时区补丁使用 可以参考https://blog.csdn.net/weixin_43885834/article/details/105745901 https://download.csdn.net/download/weixin_43885834/12360971...

    ORALCE PL/SQL程序设计第五版

    《ORACLE PL/SQL程序设计第五版》是深入学习Oracle数据库编程的重要参考资料,它涵盖了PL/SQL语言的基础到高级概念,旨在帮助读者迅速提升在Oracle环境中编写高效、可靠的存储过程和函数的能力。这本书分为上、下两...

    oracle pl/sql实例精讲student数据库模式数据和表脚本

    Oracle PL/SQL是一种强大的编程语言,它结合了SQL的数据库操作能力和Procedural Language的编程结构,用于在Oracle数据库环境中创建复杂的应用程序。在"Oracle PL/SQL实例精讲student数据库模式"中,我们将深入探讨...

    how-to-unwrap-pl-sql.zip_oracle pl/sql ppt

    PL/SQL是Oracle数据库系统中的一个关键组成部分,它是一种过程化语言,结合了SQL的查询能力与编程语言的控制结构。"如何展开PL/SQL"的主题通常涉及到理解、解析和调试PL/SQL代码,这对于Oracle数据库管理员和开发...

Global site tag (gtag.js) - Google Analytics