Technic For Faster PL SQL
Technic For Faster PL SQL
1
Tushar Gadhia
Senior Product Manager
Server Technologies Division
Oracle Corporation
Page 2
21
38
Techniques for
Developing Faster
PL/SQL Applications
Page 3
321
38
Agenda
l Reasons for Slow Execution Speed
l Identifying Problem Areas
l Correcting Performance Problems
l Future PL/SQL Performance Projects
l Conclusion
Introduction
PL/SQL is an easy-to-use, high-performance procedural language extension of SQL. Many
Fortune 500 companies have successfully used the PL/SQL platform to build mission-critical
applications. In one of the customer surveys done in 1998, it was voted as the most
important and the most satisfying feature from Oracle. It was also voted as being very
important for businesses in the next several years.
It is important to build applications that perform the necessary processing as fast and
efficiently as possible.
As with any programming language, there are a wide variety of reasons why a PL/SQL
application might not be as fast as one might hope. This presentation describes several
reasons for poor execution speed, a basic but powerful tool to help identify problem areas,
some corrective actions which might be appropriate, and some guidance regarding possible
future PL/SQL projects which might influence application tuning and design.
Page 4
4
Reasons for Slow Execution
Speed
Page 5
5
Reasons for Slow Execution
Speed
l Poorly written SQL
l Poor design
l Poor programming
l Ignorance of PL/SQL fundamentals
l Non-tuned shared pool memory
l Non-awareness of undocumented PL/SQL behavior
Page 6
6
Poorly Written SQL
l Reason for slow PL/SQL code is often badly written
SQL
l MYTH: PL/SQL consumes a LOT of time!!
l Action:
– Analyze SQL performance - determine execution
plan:
● EXPLAIN PLAN
● TKPROF
● Oracle Trace
– Redesign SQL statements
– Send proper Hints to the query optimizer
Page 7
7
Poor Design/Programming
l Poorly written algorithm
– Wrong choice of sort, search, or CPU-intensive
function
l Poor programming
– Declaring variables that are not used
– Initializations/computations which could be
pulled out of loops
– Passing unneed parameters to functions
Poor Design/Programming
Poor design and/or programming is often the result of schedule crunches or other outside
constraints. Under these circumstances, even the most experienced and knowledgeable
programmers are often likely to write code that can result in poor performance.
Poorly Written Algorithm
No matter how well-tuned a computer language might be for any given task, a slow or badly
written algorithm will dominate the performance. A poorly chosen or implemented sort,
search, or other common oft-repeated or CPU-intensive function can completely ruin an
application’s performance. Suppose that the most commonly used function in an application
is a lookup function with hundreds of possible targets. If this lookup function can be written
as a hash or a binary search, but is instead written as a linear search, the performance of
the entire application will suffer greatly. This sort of problem is much more common than
one might think.
Poor Programming
The usual items which a language optimizer might solve can cause a significant
performance problem in PL/SQL because there is not yet an optimizer phase in the
PL/SQL compiler. Some examples of this sort of problem include declaration of
variables which are not used, initializations or computations which could be pulled
out of the loops, passing unneeded parameters to functions, and so on. Usually, an
optimizer can be relied upon to clean up such problems, so sloppiness of this sort is
often not a problem and thus can creep into an application. Until PL/SQL builds an
optimizer phase into the compiler, this sort of sloppiness may cause significant
problems. Page 8
8
Ignorance of PL/SQL
Fundamentals
l Copy-in, Copy-out parameter passing
– Parameter passing and assignment semantics
differ between PL/SQL and C
l Numeric datatypes
– PLS_INTEGER is the most efficient datatype for
integer operations
● It is implemented using fast native
representations and operations
● It requires less storage than INTEGER and
NUMBER values
Page 9
9
Ignorance of PL/SQL
Fundamentals
l Implicit conversion
– PL/SQL performs implicit conversion between
structurally different datatypes
– Common with NUMBER data types
DECLARE
n NUMBER;
BEGIN
n := n + 15; -- converted
n := n + 15.0; -- not converted
...
END;
Page 10
10
Ignorance of PL/SQL
Fundamentals
l Constraint checks
– NOT NULL constraint incurs overhead
lPROCEDURE calc_m IS PROCEDURE calc_m IS
m NUMBER NOT NULL:=0; m NUMBER; --no constraint
a NUMBER; a NUMBER;
b NUMBER; b NUMBER;
BEGIN BEGIN
... ...
m := a + b; m := a + b;
... IF m IS NULL THEN
END; -- raise error
END IF;
END;
Page 11
11
Ignorance of PL/SQL
Fundamentals
l Conditional control statements
– In logical expressions, PL/SQL stops evaluating
the expression as soon as the result is
determined
– Scenario 1
– IF (sal < 1500) OR (comm IS NULL) THEN
...
–
END IF;
– Scenario 2
IF credit_ok(cust_id) AND (loan < 5000) THEN
...
END IF;
SGA
Shared pool
Page 15
15
Identifying Problem Areas
Page 16
16
Identifying Problem Areas
l Application Analysis: Evaluate performance and
identify areas that need improvement.
Page 17
17
Working with the Profiler
l The Profiler is implemented with DBMS_PROFILE
package. APIs to record information:
– START_PROFILER(run)
– STOP_PROFILER
– FLUSH_DATA
Page 18
18
Identifying Problem Areas -
Profiler
• Frequ Time per Total function fib(n pls_integer)
• -ency invocation Time return pls_integer is
begin
• 21,891 .00001187 .25996 if n = 0 then
• 4,181 .00001374 .05745 return 0;
• 17,710 .00001090 .19310 elsif n = 1 then
• 6,765 .00001446 .09783
return 1;
else
•
return fib(n-1)+
• 10,945 .00007887 .86328 fib(n-2);
• end if;
end;
•• Note:
Note:
-- information
information recorded
recorded in
in database
database tables
tables
-- simple
simple interface
interface in
in Oracle8i
Oracle8i
Page 19
19
Profiling Data
l Interpreting Profiling Data
– Critical code components
– Critical data structures
l Actions
– Tune SQL or non-SQL code?
– Algorithmic changes required?
– Select more appropriate data structure?
– Utilize any of the new 8.x features?
Profiling Data
Interpreting Profiling Data
The next step is to analyze why the time is spent in certain code segments or in accessing
certain data structures. Once again, the profiler only raises questions; it does not provides
answers.
Find the problem areas by querying the resulting performance data. Concentrate on the
packages and procedures which use a significant total amount of time, inspecting them for
all of the problems described earlier in this presentation.
The Profiler can be used to identify the critical code components and data structures, but
the users need to determine what actions to take.
Actions
The result of the analysis can be used to rework the algorithms used in the application. For
example, due to exponential growth in data, the linear search that was used in the previous
version of the application might no longer be the best choice and we might need to change it
to use a more appropriate search algorithm.
In addition, the analysis phase can point out the inefficiencies caused by the choice of
inappropriate data structures and may indicate that some other data structures need to be
chosen.
The above analysis must be considered together with the new features that are provided in
the PL/SQL 8i. These features can be used to extract more performance from the
applications. Several of tyese features are discussed later in this presentation.
Note: Even with the Profiler, one should probably focus on SQL statements, loops,
Page
recursive function invocations, assignments, and20
parameter passing as likely sources of
difficulty. 20
Tracing PL/SQL Execution
The DBMS_TRACE package provides an API for
tracing the execution of PL/SQL programs on the
server
Page 21
21
Controlling the Trace
l In large applications, enable specific subprograms
for trace
l Choose tracing levels:
– Tracing calls:
● Level 1: Trace all calls
● Level 2: Trace calls to enabled subprograms
only
– Tracing exceptions:
● Level 1: Trace all exceptions
● Level 2: Trace exceptions raised in enabled
subprograms only
Page 22
22
Correcting Performance
Problems
Page 23
23
Correcting Performance
Problems
l Repair Basic Flaws
l Use new Oracle8i performance features:
– Bulk Binds - faster PL/SQL and SQL
interaction
– NOCOPY parameter passing hint - faster
parameter passing
– Native dynamic SQL - faster execution of
dynamic SQL
Page 24
24
Repair Basic Flaws
l Tune SQL statements
l Avoid extra copies
l Do not declare variable you are not going to use
l Pull unnecessary code out of loops
l Do not pass unneeded parameters
l Remove dead code
l Apply sound design/programming techniques
l Use built-in functions whenever possible
l Select appropriate datatypes
l Avoid implicit conversion
l Avoid the NOT NULL constraint whenever possible
l Use PLS_INTEGER for integer operations
l Tune shared pool memory
Page 25
25
Binding
PL/SQL engine
SQL engine
Binding
The Oracle server has three execution engines: one each for PL/SQL, SQL, and Java. The
above diagram shows the PL/SQL and SQL engines. When running PL/SQL blocks and
subprograms, the PL/SQL engine runs procedural statements but sends the SQL
statements to the SQL engine, which parses and executes the SQL statement and, in some
cases, returns data to the PL/SQL engine. During execution, every SQL statement causes a
context switch between the two engines, which results in a performance penalty.
Performance can be improved substantially by minimizing the number of context switches
required to run a particular block or subprogram. When a SQL statement runs inside a loop
that uses collection elements as bind variables, the large number of context switches
required by the block can cause poor performance. As you may already know, collections
include nested tables, VARRAYs, index-by tables, and host arrays.
Binding is the assignment of values to PL/SQL variables in SQL statements.
Page 26
26
Bulk Binding
l Definition:
– Bind entire collection/array of values at once,
rather than loop to perform fetch, insert, update,
and delete on multiple rows
l Keywords to support bulk binding:
– FORALL instructs PL/SQL engine to bulk-bind
input collections before sending them to the SQL
engine
–FORALL index IN lower_bound..upper_bound
– sql_statement;
– BULK COLLECT instructs SQL engine to bulk-bind
output collections before returning them to the
PL/SQL engine
... BULK COLLECT INTO
collection_name[,collection_name] ...
Bulk Binding
Bulk binding is binding an entire collection at once rather than iteratively. Without bulk
binding, the elements in a collection are sent to the SQL engine individually, whereas bulk
binds pass the entire collection back and forth between the two engines.
Improved Performance
Using bulk binding, you can improve performance by reducing the number of context
switches required to run SQL statements that use collection elements. With bulk binding,
entire collections, not just individual elements, are passed back and forth.
Keywords to Support Bulk Binding
Oracle8i PL/SQL supports new keywords to support bulk binding. These are:
FORALL
The keyword FORALL instructs the PL/SQL engine to bulk-bind input collections before
sending them to the SQL engine. Although the FORALL statement contains an iteration
scheme, it is not a FOR loop.
BULK COLLECT
The keywords BULK COLLECT instruct the SQL engine to bulk-bind output collections
before returning them to the PL/SQL engine. This allows you to bind locations into which
SQL can return retrieved values in bulk. Thus you can use these keywords in the SELECT
INTO, FETCH INTO, and RETURNING INTO clauses.
Page 27
27
Bulk Binds - Examples
FORALL j IN 1..1000
INSERT INTO Orders VALUES
(orderId(j),orderDate(j),...);
SELECT orderDate
BULK COLLECT INTO oldDates
WHERE MONTHS_BETWEEN(sysdate,orderDate) > 9;
Page 28
28
Bulk Binds
FORALL ... BULK COLLECT INTO Example
FORALL j IN 1..1000
DELETE Orders
WHERE orderDate = oldDates(j) -- bulk
AND orderLoc = oldLoc -- scalar
RETURNING orderId
BULK COLLECT INTO deletedIds;
Page 29
29
When to Use Bulk Binds
l SQL statements inside PL/SQL loops
l Collection elements as bind variables
l Four or more rows processed together
Page 30
30
NOCOPY Parameter Passing
Hint
Problem in pre- 8i Releases
Copy-in
... ...
...
Copy-out
ibex =
ibex = wild goat
wild goat
word_list words
Page 31
31
When to Use Bulk Binds
l SQL statements inside PL/SQL loops
l Collection elements as bind variables
l Four or more rows processed together
Page 30
30
NOCOPY Parameter Passing
Hint
l Description:
– Ability to pass OUT and IN OUT parameters
without the overhead of copies between the
actuals and formals
l Benefit:
– Huge performance benefits (30% to 200%
faster); especially useful for passing large
structures
l Syntax:
<parameter-specification> :=
<parameter-name> IN OUT NOCOPY <type-name>
Dynamic SQL
Dynamic SQL refers to the ability to build and submit SQL statements (including DML, DDL,
transaction control, session control, and anonymous block statements) at run time.
Dynamic SQL is useful when not all of the necessary information is available at compilation
time - for example, when using a database query tool that allows you to choose query
search criteria or optimizer hints at run time. Dynamic SQL lets you do things like create a
procedure that operates on a table whose name is unknown until run time, or accept user
input that defines the SQL statement to execute.
Prior to Oracle8i, PL/SQL developers could include dynamic SQL in applications by using
the Oracle-supplied DBMS_SQL package. However, performing simple operations using
DBMS_SQL involves a fair amount of coding. In addition, because DBMS_SQL is based on
a procedural API, it incurs high procedure-call and data-copy overhead.
Page 35
35
Native Dynamic SQL
l Benefits of native dynamic SQL over DBMS_SQL:
– Highly intuitive syntax
– A lot less code
– Much easier to write & maintain code
– Much faster (30% to 400%)
Page 36
36
Native Dynamic SQL
EXECUTE IMMEDIATE statement
l Description:
Prepare, execute, deallocate dynamic SQL stmt
l Syntax:
EXECUTE IMMEDIATE <dynamic-string>
[INTO {<list-of-define-variables> |
<record-variable>}]
[USING <list-of-bind-arguments>];
where
<list-of-define-variables> :=
<define-variable> [,<define-variable>];
<list-of-bind-arguments> :=
[IN | OUT | IN OUT] <bind-argument>
[,[IN | OUT | IN OUT] <bind-argument>]...;
Page 37
37
Native Dynamic SQL -
Example
PROCEDURE insert_into_table (
table_name varchar2,
deptnumber number,
deptname varchar2,
location varchar2)
IS
stmt_str varchar2(200);
BEGIN
stmt_str := ’insert into ’ || table_name ||
’ values (:deptno,:dname,:loc)’;
EXECUTE IMMEDIATE stmt_str
USING deptnumber, deptname, location;
END;
Page 38
38
Native Dynamic SQL
EXECUTE IMMEDIATE statement vs. DBMS_SQL
PROCEDURE insert_into_table (table_name varchar2,
deptnumber number,
deptname varchar2,
location varchar2)
IS
stmt_str varchar2(200);
cur_hdl integer;
rows_processed binary_integer;
BEGIN
stmt_str := ’insert into ’|| table_name ||
’ values (:deptno, :dname, :loc);’;
cur_hdl := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur_hdl, stmt_str, dbms_sql.native);
DBMS_SQL.BIND_VARIABLE(cur_hdl, ’:deptno’, deptnumber);
DBMS_SQL.BIND_VARIABLE(cur_hdl, ’:dname’, deptname);
DBMS_SQL.BIND_VARIABLE(cur_hdl, ’:loc’, location);
rows_processed := DBMS_SQL.EXECUTE(cur_hdl);
DBMS_SQL.CLOSE_CURSOR(cur_hdl);
EXECUTE IMMEDIATE stmt_str USING deptnumber, deptname, location;
END;
Page 39
39
Transparent Performance
Improvements
l Optimization of package STANDARD builtins
l Faster anonymous block execution
l Faster RPC parameter passing
l Scalability (more users) improvements
l Caching of DLLs for improved external procedure
performance
Page 40
40
Future PL/SQL Performance
Projects
Page 41
41
Future PL/SQL Performance
Projects
l PL/SQL language optimizer
l Native compilation of PL/SQL byte code
l Native floating point datatype
l INDEX-BY tables indexed by VARCHAR2
l More transparent improvements
Page 42
42
Summary
Page 43
43
Summary
Reference Books:
Contact Info:
l Tushar Gadhia: [email protected]
l Chris Racicot: [email protected]
Page 44
44
Page 45
45