PL/SQL tuning


Performance Tuning Guide - 10g Release 1 (10.1)

PL/SQL allows us to perform many activities not available to standard SQL. If you use PL/SQL in your application, consider some of the following measures to improve the performance of your PL/SQL code:
  1. Use normal code optimization techniques. In particular, avoid unnecessary loops and place the more frequently satisfied conditions first in IF clauses.
  2. Take advantage of stored procedures and functions. Storing PL/SQL in the database avoids parsing overhead.
  3. Use explicit cursors in PL/SQL. An implicit cursor will often perform additional fetches.
  4. Use the WHERE CURRENT OF CURSOR clause to quickly access a row currently open in a cursor. Alternately, fetch and use the ROWID column if you want to avoid the overhead of the FOR UPDATE statement.
  5. Cache frequently accessed data values in PL/SQL tables.
LOOP and IF Statements
Minimize the number of iterations
       – Use EXIT to cease looping where necessary
 Remove any statements within a loop that could be processed outside the loop
       – Especially when you have nested loops
Specify the most probable condition first in a compound IF statement
       – Try to reduce the number of evaluations

Array processing
BULK COLLECT statement allows data from a query to be loaded directly into a PL/SQL table
FORALL allows data to be inserted into a table directly from a PL/SQL block
For large operations, array processing is typically 10 times faster than non-array 

WHERE CURRENT OF cursor
Inside a cursor loop, WHERE CURRENT OF allows the current row to be directly
      – This is faster than looking up the row by the primary key updated.
The cursors SQL must be defined with the FOR UPDATE clause
      – This can cause some overhead
Saving the rowid as using that for the lookup can be a useful alternative
      – But you need to check that the row has not been altered since you opened the cursor

NOCOPY clause
If a subroutine takes a PL/SQL table as an argument, a copy of the table is created for the subroutine
     – This may be time consuming, especially if the subroutine is called repeatedly
NOCOPY allows the subroutine to work on the table directly
     – This is sometimes called “passing by reference” vs. “passing by value”

Avoiding Recompilation
Use packages rather than procedures.
     – Providing the package header remains constant, changes to subroutines will not cause recompilation of dependent procedures
Pin large or performance critical packages in the shared pool
    – Dbms_shared_pool.keep

Optimizing Triggers
Ensure that triggers fire only when required
     – Use WHEN clause to restrict trigger execution to specific logical conditions
     – Use the UPDATE OF clause to restrict trigger execution to changes to specific rows

Explicit Cursors
Although you can embed SQL directly in a routine, explicitly creating a cursor is more efficient
    – An implicit cursor does a second fetch to ensure that only one row is returned
    – This is especially important if the SQL performs a table scan

Using the PL/SQL Profiler
The DBMS_PROFILER package allows you to identify hot spots in your code

Surround your PL/SQL call with
DBMS_PROFILER.START_PROFILER and
DBMS_PROFILER.END_PROFILER

The output is stored in
PLSQL_PROFILER_RUNS,
PLSQL_PROFILER_UNITS and
PLSQL_PROFILER_DATA