Tuning Oracle Stored Procedures
Guy Harrison CTO, APM Business Unit, Quest Software
Agenda
Using PL/SQL in place of standard SQL Principles of code optimization applied to PL/SQL Using array processing in PL/SQL Using and optimizing packages and procedures Optimizing PL/SQL cursors Using the PL/SQL profiler A comparison of Java and PL/SQL performance Tuning Java stored procedures
Using PL/SQL in Place of Standard SQL
Exploit a procedural approach to data processing.
Overcome optimizer limitations
Reduce client server traffic Divide and conquer complex statements Be aware of the drawbacks
Coding/maintenance overhead Inability to return result sets in many development tools
Operations that are More Efficient in PL/SQL
Finding maximums and minimums
8.1.6 analytical functions are an alternative approach
Correlated updates
The WHEN clause contains a query that is equivalent to a query in the SET clause
Any SQL statement that repeats subqueries Denormalization
Using triggers
Code Optimization 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
Example of a Poorly Formed Loop
Effect of Loop Optimization
128.65
deoptimal loop
optimal loop
0.54
20
40
60
80
100
120
140
Elapsed time (s)
Code Optimization Recursion
Recursive routines invoke themselves Elegant from a coding perspective, but consume memory and are usually slower than an iterative alternative Almost all recursive algorithms have a non-recursive equivalent
Example of Recursive and Non-Recursive Solutions
Code Optimization - Recursion
44.8
Recursive
Non-recursive
1.23
10
20
30
40
50
Elapsed Time (s)
Array Processing
The 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
Example of Array Processing
Array Processing
33.23 Insert 3.02
30.04 Select 4.73
12
18 Elapsed time (s)
24
30
36
Oracle8i PL/SQL array processing
Tradional (pre-8i) PL/SQL processing
WHERE CURRENT OF cursor
Inside a cursor loop, WHERE CURRENT OF allows the current row to be directly updated. The cursors SQL must be defined with the FOR UPDATE clause Saving the rowid as using that for the lookup can be a useful alternative
This can cause some overhead This is faster than looking up the row by the primary key
But you need to check that the row has not been altered since you opened the cursor
WHERE CURRENT OF cursor
Use primary key 33.9
Use WHERE CURRENT OF
16.2
Save ROWID
8.35
10
15
20 Elapsed time (s)
25
30
35
40
Example of WHERE CURRENT OF 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
Example of NOCOPY
Effect of NOCOPY
115.18
Not using NOCOPY
Using NOCOPY
0.04
20
40
60
80
100
120
140
Elapsed time (s)
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
Example of a Well Formed Trigger
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
Example of Explicit and Implicit Cursors
Explicit Cursors
5827 table scan 143
Implicit cursor 4 Index lookup 4 Explicit cursor
1000
2000
3000 Block gets
4000
5000
6000
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 Quests TOAD and SQL Navigator provide graphical support for the profiler
Java vs. PL/SQL Stored Procedures
Java stored procedures can be written in JDBC or SQLJ In general, Java stored procedures are more complex to write and maintain However, Java stored procedures can execute faster for computationally intensive routines
Performance Comparison Computation
19.39 Basic maths 4.11
Floating point arithmetic
0.83
148.33
15.82 Integer arithmetic 1.65
20
40
60
80
100
120
140
160
Execution Time (s) Java PL/SQL
Performance Comparison Database Intensive Routines
44.97 Batch processing 95.06 40.97 OLTP 66.38
20
40
60
80
100
Elapsed time (s) Java PL/SQL
Bind Variables in Java Stored Procedures
Unlike PL/SQL, bind variables are not transparently implemented in JDBC Although using bind variables requires extra coding, using literals will increase parse overhead and cause contention You should use Prepared statements in JDBC An alternative is to issue an ALTER SESSION SET CURSOR_SHARING=FORCE
Array Processing in JDBC
As in PL/SQL, you should use array processing where appropriate
Use the setFetchSize method for queries Use the addBatch and executeBatch methods for inserts
Thank you