techniques tuning plsql apps twp
Transcript of techniques tuning plsql apps twp
-
8/14/2019 techniques tuning plsql apps twp
1/26
Techniques For Tuning PL/SQL
Applications
An Oracle Technical White Paper
M arch 199 9
-
8/14/2019 techniques tuning plsql apps twp
2/26
Techniques For Tuning PL/ SQL Applications
March 1999
2
INTRODUCTION
Oracle8i PL/SQL
provides seamless and tight integration with SQL and the Oracle server. Oracle
PL/SQL is widely used for building scalable, portable, and robust enterprise applications. As
organizations grow, there is a need to make the applications that service them more scalable and
faster. Moreover, due to the explosive growth of the amount of available data, performance has now
become a critical issue, even for customers who have not modified their existing applications.
Oracle8i PL/SQL has several new features that improve application performance and increase
scalability, by optimizing memory usage. Some of these features are transparent to the end user and,
with simple recompilation, will improve the performance of existing applications. Other features
require the use of new syntax and, therefore, the modification of existing applications, to exploit the
benefits that the new features offer.
To improve application performance and scalability, the following sequence of steps needs
to be executed:
= Evaluate performance of existing applications, and identify bottlenecks/areas for improvement.= Analyze the characteristics of the application code that needs improvement, and identify the
relevant features that can be used for improving performance.
=Develop/modify the application so that they can use features and performance tips to extract themaximum performance.
This paper describes the PL/SQL tools and features for implementing the above methodology, in the
following order:
= A discussion of the use of profiling tools for benchmarking existing applications and identifyingareas for improving performance.
= A descript ion of the features that can significantly improve performance. In addition toperformance improvements, this paper also discusses the memory usage improvements of PL/SQL
programs. Significant improvements have been made to reduce the session memory (also called,
UGA user global memory) that PL/SQL requires, resulting in better PL/SQLapplication scalability.
= Some PL/SQL performance tips that can be used for improving application performanceand scalability.
-
8/14/2019 techniques tuning plsql apps twp
3/26
Techniques For Tuning PL/ SQL Applications
March 1999
3
APPLICATION A NA LYSIS
As mentioned in the introduction, the first step in improving an application's performance is to
identify the characteristics of the application and the bottlenecks in the code. This will allow the
developer to determine the portions of the application where the maximum time is spent, which, in
turn, allows att ention to be focused on the relevant program segments and data structures. The
Profiling tool described below can be used to analyze PL/SQL applications.
PROFILING
As Oracle8i PL/SQL users develop increasingly large numbers of PL/SQL packages that are used as
components, the need to ident ify and isolate performance problems becomes critical. Oracle8i
provides a profiler, with which customers can:
= Profile their existing PL/SQL applications.= Locate bottlenecks.= Focus on improving the performance of any bottlenecks found.
Using the profiling tool, application developers can generate profiling information for all named
library units used in a single session. The profiling information is stored in a database, to help
generate information on time spent in each PL/SQL line, module, and routine. A sample textual
report writer is provided (refer to [7] for more details). The report writer can extract the persistent
profiling information that the profiler stores, to identify the time spent at each line. Thus, it allows
application developers to identify the program segments that need improvement.
Once the program segments that require improvements have been identified, the next step is to
analyze why time is spent in certain code segments. The feedback from the profiler can be used to re-
work the algorithms (or perhaps select new algorithms) used in the application. In addition, the
analysis phase can point out inefficiencies caused by the choice of inappropriate data structures. This
information must be considered together with the new features that PL/SQL provides, to identify
whether more performance can be extracted from the applications. To conclude, application analysis
is an important phase that drives the rest of the application tuning effort that developers undertake.
-
8/14/2019 techniques tuning plsql apps twp
4/26
Techniques For Tuning PL/ SQL Applications
March 1999
4
PL/SQL FEATURES FOR IM PROVING PERFORMAN CE
Oracle8 PL/SQL Release 8.0 and Oracle8i PL/SQL Release 8.1 support a variety of new features that
can be used to develop more efficient applications. The following sections describe the new features
that have been added to the language. In addition, Oracle devoted a lot of effort towards
transparently improving the performance of the existing Oracle PL/SQL applications.
NEW FEATURES IN ORACLE8 IPL/SQL
As summarized in the table below, several new capabilities have been added in Oracle8i PL/SQL in
the areas of performance.
PROGRAM
CHARACTERISTICS
IMPROVEMENT FEATURE
Applications that execute SQL
statements in a loop
Faster data transfer between
PL/SQL and SQL
Bulk Binds
Applications that contain
functions/procedures that pass
large records, ADTs, or
collections as parameters
Faster parameter passing mode NOCOPY
Applications that use the
DBMS_SQL package
Faster support for dynamic SQL
statements
Native dynamic SQL
Applications that implement
computational business logic
with few database (SQL)
operations
Efficient and convenient
alternative to implement
compute-intensive code
External Procedures
The following sections describe these features in more detail.
-
8/14/2019 techniques tuning plsql apps twp
5/26
Techniques For Tuning PL/ SQL Applications
March 1999
5
Bulk Binds: Faster Data Transfer Betw een PL/SQL and SQL
The PL/SQL interpreter executes all the procedural statements, but sends the SQL statements to the
SQL engine, which parses and executes the SQL statements and, in some cases, returns data to the
PL/SQL engine. Although this execution path has been heavily optimized, to support faster
execution of the embedded SQL statements, the context switch adds some overhead. The
performance penalty can become noticeable when SQL statements are nested in loops, as
demonstrated in the following example:
-- Assume that orderId, orderDate, etc. (one for each column
of the
-- table Orders) have been filled appropriately with all thenew
-- Orders that need to be inserted into the database. Assume
that
-- there are 1000 orders.
FOR i In 1..1000
LOOP
INSERT INTO Orders VALUES (orderId(i), orderDate(i), ...);
END LOOP;
The overhead can be reduced, by minimizing the number of context switches. The bulk binds
features allow users to decrease the overhead, by operating on multiple rows in a single DML
statement. With bulk binds, entire collections, not just the individual collection elements, are
passed back and forth between PL/SQL and SQL engines. Oracle8i PL/SQL supports new
keywords FORALL and BULK COLLECT to support bulk binds. The above example may be
transformed as follows, to use bulk binds:
-
8/14/2019 techniques tuning plsql apps twp
6/26
Techniques For Tuning PL/ SQL Applications
March 1999
6
FORALL i In 1..1000
INSERT INTO Orders VALUES (orderId(i), orderDate(i), ...);
For more details regarding this feature, please refer to [2].
NOCOPY: Faster Parameter Passing
PL/SQL supports three parameter passing modes:
= IN parameters are passed by reference.= IN OUT parameters are implemented as copy-in/copy-out.= OUT parameters are implemented as copy-out.
This copying protects the original values of the arguments, if exceptions are raised in the called
function/procedure. However, such copying imposes CPU and memory overhead, especially when
the parameters involved are large data structures, such as large strings or collections.
In Oracle8i, PL/SQL supports a new "NOCOPY" modifier that can be used to avoid this overhead, by
allowing IN OUT and OUT parameters to be passed efficiently by reference, when possible. Use of
this new modifier will result in performance improvements for any application that passes large data
structures as IN OUT or OUT parameters. The following example shows the use of the
NOCOPY modifier.
-- The IN OUT parameter "word_list" in "add_entry" is passed
by
-- reference when possible
TYPE Definition IS RECORD (
word VARCHAR2(20),
meaning VARCHAR(200)
-
8/14/2019 techniques tuning plsql apps twp
7/26
-
8/14/2019 techniques tuning plsql apps twp
8/26
Techniques For Tuning PL/ SQL Applications
March 1999
8
DBMS_SQL package. In addition, the DBMS_SQL approach is based on a procedural API and, as a
result, suffers from high procedure call and data copy overhead. We have seen significant
performance improvements (up to 200%) over DBMS_SQL in our small benchmarks.
For example, consider the following program segment that demonstrates the use of DBMS_SQL. It
also illustrates the use of native dynamic SQL. Please refer to [3] for more details.
DML example, using the
DBMS_SQL package
Equivalent DML example with
Native Dynamic SQL
PROCEDURE insert_into_table
(table_name VARCHAR2,
deptnumber NUMBER,
deptname VARCHAR2,
location VARCHAR2)
IS
cur_hdl INTEGER;
stmt_str
VARCHAR2(200);
rows_processed
BINARY_INTEGER;
BEGIN
stmt_str := 'insert into
' || table_name || ' values
(:deptno,
:dname, :loc)';
-- open cursor
cur_hdl :=
dbms_sql.open_cursor;
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)';
-- bundled execution using
native dynamic SQL
EXECUTE IMMEDIATE stmt_str
USING
deptnumber, deptname,
location;
END insert_into_table;
-
8/14/2019 techniques tuning plsql apps twp
9/26
Techniques For Tuning PL/ SQL Applications
March 1999
9
-- parse cursor
dbms_sql.parse(cur_hdl,
stmt_str, dbms_sql.native);
-- supply binds
dbms_sql.bind_variable(cur_hd
l, ':deptno', deptnumber);
dbms_sql.bind_variable(cur_hd
l, ':dname', deptname);
dbms_sql.bind_variable(cur_hd
l, ':loc', location);
-- execute cursor
rows_processed :=
dbms_sql.execute(cur_hdl);
-- close cursor
dbms_sql.close_cursor(cur_hdl
);
END insert_into_table;
On every bind, the DBMS_SQL package implementation makes copies of the PL/SQL bind variable
into its space, for use during the execution phase. Similarly, on every fetch, the data is first copied
into the space that the DBMS_SQL package manages. Therefore, the fetched data is copied, one
column at a time, into the appropriate PL/SQL variables, resulting in a significant data
copying overhead.
-
8/14/2019 techniques tuning plsql apps twp
10/26
Techniques For Tuning PL/ SQL Applications
March 1999
10
External Procedures: Faster Execution of Compute-Intensive Logic
Oracle8 PL/SQL Release 8.0 provided support for external procedures, which allow a simple, easy,
and safe way to interface external systems and 3GL application code with the database server, while
preserving transactional semantics. They can be called from a number of different contexts,
including from SQL, PL/SQL stored procedures, functions and triggers, client OCI, and
Precompiler programs.
Several optimizations were done in Oracle8i PL/SQL Release 8.1 that decrease the overhead
associated with callouts. Customers migrating from Oracle8 to Oracle8i can take advantage of the
performance benefit, by merely recompiling their applications.
PL/SQL is closely tied to the Oracle Server, for SQL transaction processing. Complex number
crunching can be very expensive in PL/SQL and is best done efficiently, in lower level languages like
C. Consider the following CPU-int ensive PL/SQL code fragment for computing the
Fibonacci numbers:
CREATE FUNCTION fib(n PLS_INTEGER) RETURN PLS_INTEGER IS
BEGIN
IF (n < 2)
RETURN n;
ELSE
RETURN (fib(n-2) + fib(n-1));
END IF;
END;
And the C fragment:
-
8/14/2019 techniques tuning plsql apps twp
11/26
Techniques For Tuning PL/ SQL Applications
March 1999
11
unsigned int fib(n)
unsigned int n;
{
if (n < 2)
return n;
else
return (fib(n-2) + fib(n-1));
}
Our experiments have shown that C code performs better than PL/SQL, even for values as
small as N=10.
TRANSPARENT PL/SQL PERFORMANCE IMPROVEMENTS
The Oracle8i PL/SQL Release 8.1 runtime engine has been further tuned to allow existing
applications to run faster transparently. The following table highlights these as well as
improvements made in Oracle8 PL/SQL Release 8.0:
-
8/14/2019 techniques tuning plsql apps twp
12/26
Techniques For Tuning PL/ SQL Applications
March 1999
12
Program Characteristics Feature Release
Applications that use the standard builtins
provided by PL/SQL
Optimization of Package STANDARD
Builtins
8.1
OCI, SQL*Plus, DBMS_SQL, etc.
applications that invoke PL/SQL stored
procedures, by building anonymous blocks
Faster Anonymous Block Execution 8.1
Applications that make RPC calls (client-
to-server or server-to-server) and pass large
records, ADTs, and collections
RPC Parameter Passing Improvements 8.1
Application uses triggers, and calls PL/SQL
functions from SQL context
Faster Calling PL/SQL from SQL Context 8.0
All applications Code-generation optimizations to minimize
temporaries
8.0
Applicat ions that use records Efficient Implementat ion of PL/SQL
Records
8.0
Applications that use collections Improved PL/SQL Index-By Table
Implementation
8.0
Optimization of Package STANDARD Built-Ins
Calls to package Standard built-ins (for example, TO_CHAR, TO_DATE, SUBSTR, etc.) were
improved in Oracle8i PL/SQL, by optimizing the code path to call such built-ins, resulting in faster
execution. This is a huge transparent improvement, because most applications are heavy users of
these built-ins. Our benchmark runs have shown performance gains of 10-30%. The performance
gains become more significant if built-ins are used more heavily in the application.
-
8/14/2019 techniques tuning plsql apps twp
13/26
Techniques For Tuning PL/ SQL Applications
March 1999
13
Faster Anonymous Block Execution
The following improvements were made in Oracle8 i PL/SQL Release 8.1:
=The invocation of anonymous blocks with bind variables has doubled in speed, due to elimination ofconsiderable code path in bind variable processing.
= Accessing elements of host array bind variables is significantly faster in Oracle8i PL/SQL.= We now optimize host binds that are used only in SQL statements, in anonymous PL/SQL blocks,
by avoiding unnecessary temporaries.
= Redundant rebinds for host bind variables to SQL statements in an anonymous block have beeneliminated for repeated executions of the anonymous block.
In addition, and perhaps more significantly, calling PL/SQL functions and triggers from SQL will
now be much faster, because this is internally implemented, using anonymous blocks with
bind variables.
RPC Parameter Passing Improvement
The overhead associated with RPC parameters has been reduced in Oracle8i PL/SQL Release 8.1, by
eliminating some redundant temporaries. Any call that passes large records, ADTs, or collections
(including index-by tables) will benefit from this optimization. This optimization is applicable to
the server-to-server, as well as client-server RPC calls.
Faster Calling PL/ SQL From SQL Context
The overhead of calling PL/SQL functions (or triggers) from SQL context has been made negligible in
Oracle8 PL/SQL Release 8.0. Several optimizations were done in this area. Anonymous blocks built
for invoking PL/SQL from SQL are now compiled and kept as part of the parent SQL cursor. A
critical latching bottleneck, which made PL/SQL invocation in Parallel Query operations very
expensive, has been eliminated. Some structures (for example, date context) are now cached in the
PL/SQL interpreter context. As a result, repeated invocations of PL/SQL (for example, on every row
of a SQL query) have been made more efficient. Invocation of anonymous blocks with bind variables
is much faster (as described in the previous section).
-
8/14/2019 techniques tuning plsql apps twp
14/26
Techniques For Tuning PL/ SQL Applications
March 1999
14
Code Generation of Optimizations to Minimize Use of Temporaries (Oracle8Improvement)
Code generation optimizations were done to minimize the use of temporaries during expression
evaluation, thereby resulting in smaller and more efficient MCODE. For example, consider the
following PL/SQL statement:
str1 := str2 || str3;
In PL/SQL Releases 2.x, the result of the expression, "str2 || str3," would be computed into a
temporary variable, and then the temporary would be copied to the variable "str1," with appropriate
constraint checking. From PL/SQL Release 8.0 on, a single byte-code instruction is generated to
compute and store the result of the concatenation directly into "str1."
This significantly improves execution time, by reducing the amount of data copy and the time spent
in creation of temporaries. This temporary elimination optimization also applies to assignment
statements involving implicit conversions, such as:
number_variable := pls_integer_variable;
number_variable := char_variable;
For the above statements, temporaries are no longer generated to hold the result of the type
conversion. The left-hand side variable is directly used as the target of the conversion.
Efficient Implementation of PL/ SQL Records
In PL/SQL Release 2.3.4 and earlier releases, there was no true support for RECORDs in the run-
time. The compiler exploded a RECORD into its individual scalar fields, which resulted in
inefficient code. Starting with Release 8.0, the PL/SQL run-time provides native support for
composite types, such as RECORDs and OBJECTs. The run-time uses structural type descriptors,
generated during compilation, to implement operations (such as "copy," "RPC argument
marshaling,", etc.) on data items of these types.
-
8/14/2019 techniques tuning plsql apps twp
15/26
Techniques For Tuning PL/ SQL Applications
March 1999
15
Improved PL/ SQL Index-By Table Implementation
Collection data types (index-by tables, nested tables, and varrays) have been implemented using a
new paged-array representation. This replaces the previous B-tree-based implementation for index-
by tables, which had the disadvantage that there could be a lot of data movement during insert
operations, due to tree balancing.
Operations such as lookup, insert, and copy should be faster now. For dense collections, especially,
the paged-array scheme exhibits much better memory utilization characteristics than the previous B-
tree scheme.
Other Enhancements
A number of other enhancements have been added that make PL/SQL execution efficient. This list
includes faster implementations for:
= Byte-code operand fetches.= Scope (procedure frame) entry and exit (by speeding up interpreter's register save/restore operations).= Common built-in operations, like "to_char" on numeric types.= Access to a package's own global variables.= Bind variable reads/writes.= Dynamic SQL that uses DBMS_SQL.= Assignments to numbers without scale and precision constraints.= Null initialization of frame variables on entry to scope.= Runtime code used for executing the RETURNING INTO clause of SQL DML statements was
tuned to reduce overhead.
TRANSPARENT M EMORY USAGE IMPROVEMENTS
The scalability of large applications directly depends on the memory requirement of the application
code. In addition to the performance improvements, the memory management in Oracle8 has been
tuned to reduce the memory usage of the applications. The size of PL/SQL MCODE (compiled byte-
-
8/14/2019 techniques tuning plsql apps twp
16/26
Techniques For Tuning PL/ SQL Applications
March 1999
16
code form), which is loaded in system global memory (SGA), is down about 20-25%, compared to
Oracle7. Major improvements have been made in reducing user global memory (UGA) that PL/SQL
packages performing SQL operations consume.
For applications such as Oracle Office, the UGA consumption due to PL/SQL packages is down about
40%. These improvements have played a crucial role in enabling Oracle8 applications to scale to
tens of thousands of users (see [1]). The key improvements are summarized in the table below:
Program Characterist ics Feature Release
All applications Reduction in Shared Pool (SGA)
fragmentation
2.3, 8.0
All applications Reduction in SGA utilization 8.0
Applications with SQL statements Reduction in UGA, due to
Improvements in Embedded SQL
Execution
8.0
Applications that have variables of
VARCHAR2 and RAW datatypes
Dynamic Allocation of Large
VARCHAR2 and RAW variables
8.0
Applications that dont need to maintainstate across calls to the server
Serially Reusable Packages 8.0
The following sections describe these improvements in more detail.
Reduction in Shared Pool (SGA) Fragmentation
On the server, the SGA is implemented using shared memory a range of virtual addresses is
mapped to the shared segment on every Oracle process. As an Oracle instance continues to servicerequests, the free SGA memory tends to become fragmented, thus making it harder to satisfy
requests for large chunks.
Execution of a PL/SQL library unit involves loading it s MCODE into SGA memory. Two major sub-
pieces of the MCODE are the code segment and constant pool. The code segment contains the
-
8/14/2019 techniques tuning plsql apps twp
17/26
Techniques For Tuning PL/ SQL Applications
March 1999
17
byte-code (or the instruction) sequence for the program. The constant pool piece holds the literal
constants in the program, as well as various other descriptors that the interpreter uses to perform
tasks, like PL/SQL RPC, exception processing, SQL processing, and so on.
Until PL/SQL V2.2, the code segment and the constant pool pieces were allocated as contiguous
chunks in the SGA. In PL/SQL V2.3, code segment paging was implemented, which helped alleviate
some of the SGA fragmentation concerns. In PL/SQL V8, the constant pool portion of the PL/SQL
MCODE is also paged.
Virtual machines that implement paging completely at load time suffer from the problem that
instructions or literal data can span page boundaries, and, hence, such VMs need to check for page
faults during instruction or literal data fetches. This can result in poor performance. In contrast, one
of the salient characteristics of PL/SQL paging is that parts of the paging logic have been designed
right into the compiler, which guarantees that no instruction or literal data item will span page
boundaries. This characteristic helps minimize the number of page table lookups, and also
eliminates the need to do any segmented fetches at run-time.
Reduction in SGA Utilization
The SGA memory consumpt ion of PL/SQL libraries has been considerably reduced. The MCODE
size of a PL/SQL library unit in V8 is about 20-25% less than in V7. Some of the optimizations doneto achieve this were:
= The use of a compression scheme in the byte-code operand specification.= Initialization of variables upon entry into a scope that uses a compact descriptor, which lives in the
constant pool part of the MCODE, instead of using individual byte-code instructions.
Reduction in UGA Due to Improvements in Embedded SQL Execution
In V8 there has been a substantial improvement in the execution model for SQL statements
embedded in PL/SQL, which resulted in substantial UGA memory savings and performance
improvements. The UGA memory consumption of PL/SQL packages is down about 40% compared
to Oracle7, due to these changes. Previously, for SQL executed from PL/SQL, a contiguous buffer
would be allocated in UGA to hold the values of the input and output variables for the SQL
-
8/14/2019 techniques tuning plsql apps twp
18/26
Techniques For Tuning PL/ SQL Applications
March 1999
18
statement. An extra copy step was needed to move data between this buffer and the actual PL/SQL
variables in the SQL statement. Although this buffer would be reused if the SQL statement was to be
executed again, the main disadvantage is that it remains allocated in the UGA till the end
of the session.
In V8, these input/output buffers have been eliminated. Instead, the binds and defines to the SQL
statement are done directly, using the PL/SQL variables, thus saving both time spent on the extra
copy step and UGA memory.
Dynamic Allocation of Large VARCHAR2 and RAW Variables
In Oracle8 PL/SQL, variables of type VARCHAR2 and RAW are dynamically allocated and resized
as appropriate. They are no longer pre-allocated on the PL/SQL execution stack to their maximum
declared size. This should greatly reduce the memory utilization for applications that pessimistically
declare large VARCHAR2s/RAWs, but often end up storing only small amounts of data in them.
Observe that, for package global VARCHAR2 and RAW variables, this implies savings in UGA
memory. As an optimization, since heap allocated items tend to have a slight performance overhead,
small VARCHAR2s and RAWs are pre-allocated on the PL/SQL execution stack (like in V7).
Serially Reusable Packages
Before Oracle8 PL/SQL, the UGA memory of a package simply stayed around until the end of the
session, whether or not the application needed it anymore. This limits scalability, since such
memory grows linearly with the number of users.
To help applications better manage memory usage, PL/SQL provides the pragma
SERIALLY_REUSABLE, which lets users mark some packages as "serially reusable." You can so
mark a package if its state is needed only for the duration of a call to the server (for example, an OCI
call to the server, a PL/SQL client-to-server or server-to-server RPC).
The global memory for such packages is not kept in the UGA per user, but instead in a small SGA
pool. At the end of the call to the server this memory is returned to the pool for reuse. Before reuse,
the package global variables are initialized to NULL, or to the default values provided.
-
8/14/2019 techniques tuning plsql apps twp
19/26
Techniques For Tuning PL/ SQL Applications
March 1999
19
The pool is kept in SGA memory, so that the work area of a package can be reused across users who
have requests for the same package. In this scheme, the maximum number of work areas needed for a
package is only as many as there are concurrent users of the package, which is typically much fewer
than the total number of logged on users. The use of "serially reusable" packages does increase the
shared-pool requirements slightly, but this is more than offset by the decrease in the per-user UGA.
Further, Oracle ages out work areas not in use, when it needs to reclaim shared pool memory.
PL/SQL PERFORMANCE TIPS
As mentioned in the introduction, three steps are required to improve application performance and
scalability. First, analyze the performance of the application, to identify the areas for improvement.
Second, determine the relevant features that can be used to improve the performance. Finally,
develop/modify the application, so that it can use features that extract maximum performance.
This section provides some PL/SQL performance tips for writ ing efficient PL/SQL code. These tips
can be used to improve the performance of PL/SQL applications.
VARRAYs vs. Nested Tables
Oracle8 offers two new collection types: nested tables and varrays. An important difference is that
varrays have a maximum declared size, whereas nested tables are unbounded. As a result, in Oracle,
varray data is stored in-line (in the same tablespace), but nested table data is stored out-of-line in a
separate table. This implies that storing/retrieving varrays typically involves fewer disk accesses.
Hence, they are more efficient than nested tables. Our experiments indicate that the varrays are 5-
10% faster than nested tables. However, the difference should increase as the varrays are
optimized further.
Nested Tables vs. Index-By Tables
Nested tables require explicit initialization, while index-by tables are automatically init ialized. In
addition, nested tables need to be explicitly extended, while index-by tables are automatically
extended when a larger subscript is encountered. As a result, nested tables are densely allocated,
while index-by tables are not. Due to these reasons, nested tables are more efficient than index-by
-
8/14/2019 techniques tuning plsql apps twp
20/26
Techniques For Tuning PL/ SQL Applications
March 1999
20
tables. A nested table can replace a dense index-by table, to extract performance benefits in the range
of 10-30% for tables with 100 to 1000 scalar elements.
Integer Operations in PL/SQL
PL/SQL supports PLS_INTEGER as a native datatype: the operations on PLS_INTEGER are
performed by the PL/SQL interpreter itself. Numeric types, such as INTEGER and NUMBER, are
represented in the 22 byte Oracle number format. Oracle number libraries are used to implement
arithmetic operations on these types. Furthermore, the INTEGER type is a constrained subtype of
NUMBER with a precision of 0. On assignments to INTEGER variables, precision checking is done
at run-time.
Both PLS_INTEGER and BINARY_INTEGER are both represented as a signed 4-byte quantity
("sb4"). But, BINARY_INTEGER arithmetic is costly: the operands are first converted to Oracle
number and then the Oracle number library is used to compute the result as another Oracle number.
This results in increased use of temporaries and data conversion, and, hence, poor performance. On
the other hand, native integer arithmetic is used to efficiently implement arithmetic operations on
PLS_INTEGERs.
The numeric types NATURAL, NATURALN, POSITIVE, POSITIVEN, and SIGNTYPE are
subtypes of BINARY_INTEGER (refer to [5] for details) with "stricter" range constraints. There isconsiderable overhead (about 3-4 byte-code instructions) in the enforcement of these range
constraints on every assignment (or parameter passing) to variables of these types.
Record of Tables vs. Table of Records
A collection of a related set of values can be stored either as record of tables or table of records. Since
the record of tables requires maintaining tables of scalars, the elements are stored in-line. However,
elements are stored out-of-line for table of records. The table below shows a code fragment that
demonstrates the benefit of using a record of tables.
-
8/14/2019 techniques tuning plsql apps twp
21/26
Techniques For Tuning PL/ SQL Applications
March 1999
21
Table of Records Record of Tables
DECLARE
...
T Y PE ae_li ne_rec_type IS REC ORD
(
source_id N UM BER ,
source_table VA RCH A R2 (30 ),
account N UM BER ,
entered_dr NUMBER,
entered_cr N UM BER ,
accounted_dr N UM BER ,
accounted_cr NU M BER ,
currency_code VA RCH A R2 (3 0),
exchange_rate_type VA RCH A R2 (30 ),
exchange_rate N U M BER ,
exchange_date DA T E,
description VARCHAR2(240),
third_party_id NUMBER,
third_party_site_id NU M BER
);T Y PE tbl_type IS T A BL E of rec_type;
...
BEGIN
...
EN D;
DECLARE
....
T Y PE num_arr IS TA BL E OF number;
T Y PE char30_arr IS T A BL E OF varchar2(30) ;
TY PE char240_ arr IS TA BLE OF varchar2(240 );
T Y PE date_arr IS TA BL E OF date;
T Y PE rec_type IS RECORD
(
source_id num_arr,
source_table char30_arr,
account num_arr,
entered_dr num_arr,
entered_cr num_arr,
accounted_dr num_arr,
accounted_cr num_arr,
currency_code char30_arr,
exchange_rate_type char30_arr,
exchange_rate num_arr,
exchange_date date_arr,description char240_arr,
third_party_id num_arr,
third_party_site_id num_arr
);
BEGIN
...
EN D;
Benchmark results indicate that the record of tables is an order of magnitude faster than the table of
records, for records/tables with 10,000 elements.
Constrained Datatypes
Using NOT NULL constraint s in PL/SQL incurs performance penalty. Consider the
following program:
PROCEDURE proc IS
m NUMBER NOT NULL;
a NUMBER;
b NUMBER;
-
8/14/2019 techniques tuning plsql apps twp
22/26
Techniques For Tuning PL/ SQL Applications
March 1999
22
BEGIN
m : = a + b ;
m := m * 1.2;
m : = m * m ;
...
END;
Since "m" is a NOT NULL constrained number, the result of the expression "a+b" is first computed
into a temporary, and the temporary is then tested, to ensure it is not NULL. If the temporary is
NULL an exception is raised, otherwise the value of the temporary is moved to "m." On the other
hand, if "m" was not constrained, then the result of the expression "a+b" could directly be computed
into "m." So, a more efficient way to rewrite the above fragment with reduced use of temporaries is:
PROCEDURE proc IS
m NUMBER; -- Note: m doesn't have NOT NULL constraint
a NUMBER;
b NUMBER;
BEGIN
m : = a + b ;
m := m * 1.2;
-
8/14/2019 techniques tuning plsql apps twp
23/26
Techniques For Tuning PL/ SQL Applications
March 1999
23
m : = m * m ;
-- enforce constraint programmatically
IF (m IS NULL) THEN
-- raise appropriate error
END IF;
...
END;
Another thing to note is that the types NATURALN and POSTIVEN are defined to be NOT NULL
subtypes of NATURAL and POSITIVE, respectively. Hence, users will incur the performance
penalty described above when using them. Similarly, assignment among the datatypes with different
range constraints (for example, POSITIVE and BINARY_INTEGER) also incur constraint
checking overhead.
Avoid Type Conversions
PL/SQL does implicit conversions between structurally different types at run-time. Currently, this is
true even when the source item is a literal constant . A common case where implicit conversions
result in a performance penalty, but can be avoided, is with numeric types. For instance, assigning a
PLS_INTEGER variable to a NUMBER variable, or vice versa, will result in a conversion, since their
representations are different. Such implicit conversions can happen during parameter passing as well.
-
8/14/2019 techniques tuning plsql apps twp
24/26
Techniques For Tuning PL/ SQL Applications
March 1999
24
Some examples of inefficient code and suggestions to fix them are given below:
= Prevent conversions between numeric types. For example:number_variable := number_variable + 1;
The literal constant 1 is represented as a native integer. It gets converted to the Oracle NUMBER
format before the addit ion. Instead, use:
number_variable := number_variable + 1.0;
The above is more efficient, because literal floats (like 1.0) are represented as Oracle number, so no
type conversion happens at run-time. Or better still, when dealing with integer data, use:
pls_integer_variable := pls_integer_variable + 1;
= Prevent numeric to character type conversion. For example,char_variable := 10;
The literal 10 is converted to CHAR at run-t ime, and then copied. Instead, use:
char_variable := '10';
CONCLUSIONS
PL/SQL is a customer-centric language Oracle maintains the language specifications and provides
the required execution environment. Oracle intends to continue working with the large PL/SQL
customer base to evolve and enhance the language and execution environment to match user
requirements. Oracle intends to aggressively improve performance, by working on the
following projects:
= Oracle is considering compilation of PL/SQL to C, which will transparently improve theperformance of all PL/SQL applications by native compilation and avoidance of interpreter overhead.
= Oracle plans to significantly optimize the runtime engine, to allow applications to be automaticallyself tuned, as well as to investigate performance hints at compile time that will help customers
manually tune their applications.
= Oracle also plans to enhance the profiler, so that customers can find bottlenecks more easily.
-
8/14/2019 techniques tuning plsql apps twp
25/26
Techniques For Tuning PL/ SQL Applications
March 1999
25
ACKNOWLEDGEMENTS
The authors of this paper, Ajay Sethi (Editor), Kannan Muthukkaruppan, Chris Racicot, Ashok
Swaminathan, Ron Decker, Radhakrishna Hari, Chandrasekharan Iyer, Sanjay Krishnamurthy, Neil
Le, Shirish Puranik, Ian Stocks and Murali Vemulapati thank the PL/SQL Product Development
team for reviewing the paper. In particular, the authors thank Chandrasekharan Iyer, Thomas
Kurian, Kannan Muthukkaruppan, Shirish Puranik and Ashok Swaminathan for reviewing the paper
and for their useful suggestions for improving the paper.
REFERENCES
1. Scaling to Thousands of Users with Oracle8, Amit Jasuja and William Maimone, European Oracle
User's Conference, Vienna, 1997.
2. Bulk Binds: Faster SQL Execution in PL/SQL, Sanjay Krishnamurthy, Ajay Sethi, and Ashok
Swaminathan, Oracle8i PL/SQL Whitepaper, 1998.
3. Native Dynamic SQL in PL/SQL, Kannan Muthukkaruppan, Neil Le, and Ashok Swaminathan,
Oracle8i PL/SQL Whitepaper, 1998.
4. NOCOPY: Faster Parameter Passing in PL/SQL, Ajay Sethi and Chandrasekharan Iyer, Oracle8i
PL/SQL Whitepaper, 1998.
5. PL/SQL User's Guide and Reference, Oracle8i, 1998.
6. Improving Performance of PL/SQL Applications - Advances in Oracle8, Kannan Muthukkaruppan,
Oracle Open World '97.
7. Oracle8i Server Application Developer's Guide, Oracle8i, 1998.
-
8/14/2019 techniques tuning plsql apps twp
26/26
Oracle Corporation
World Headquarters
500 Oracle Parkway
Redwood Shores, CA 94065U.S.A.
Worldwide Inquiries:
+1.650.506.7000
Fax +1.650.506.7200
http:// ww w.oracle.com/
Copyright Oracle Corporation 1999
All Rights Reserved
This document is provided for informational purposes only, and
the information herein is subject to change without notice.
Please report any errors herein to Oracle Corporation. Oracle
Corporation does not provide any warrant ies covering and
specifically disclaims any liability in connection w ith t his
document.
Oracle and ConText are registered trademarks, and Oracle8i,
Oracle8, Oracle7, PL/SQL, Pro*C and Oracle Developer are
trademarks or registered trademarks of Oracle Corporation. All
other company and product names mentioned are used for
identification purposes only and may be trademarks of their
respective owners.