Routine type: procedure, function, method |
- Procedures, functions, and methods serve different purposes and
are referenced in different places. Their functional differences
make it difficult to compare their performance directly.
- In general procedures can sometimes be rewritten as functions
(particularly if they return a scalar value and only query data) and
enjoy slight performance improvements, however these benefits are
generally a result of simplifying the SQL required to implement the
SQL logic.
- User-defined functions with complex initializations can make use
of scratchpads to store any values required in the first invocation
so that they can be used in subsequent invocations.
|
Routine implementation: system-defined or user-defined |
- For equivalent logic, built-in routines perform the best, followed
by system-defined routines, because they enjoy a closer relationship
with the database engine than do user-defined routines.
- User-defined routines can perform very well if they are well coded
and follow best practices.
|
Routine implementation: SQL or external routine implementation |
- SQL routines are more efficient than external routines because
they are executed directly by the DB2® database
server.
- SQL procedures generally perform better than logically equivalent
external procedures.
- For simple logic, SQL function performance will be comparable
to that of an equivalent external function.
- For complex logic, such as math algorithms and string manipulation
functions that require little SQL, it is better to use an external
routine in a low level programming language such as C because there
is less dependence on SQL support.
- See Comparison of routine implementations for a comparison of the features, including performance,
of the supported external routine programming language options.
|
External routine implementation programming language |
- See: Comparison of supported APIs and programming languages for external routine development for a comparison of the
performance features that you should consider when selecting an external
routine implementation.
- Java™ (JDBC and SQLJ APIs)
- Java routines with very
large memory requirements are best created with the FENCED NOT THREADSAFE
clause specified. Java routines
with average memory requirements can be specified with the FENCED
THREADSAFE clause.
- For fenced threadsafe Java routine
invocations, DB2 attempts to
choose a threaded Java fenced
mode process with a Java heap
that is large enough to run the routine. Failure to isolate large
heap consumers in their own process can result in out-of-Java-heap
errors in multi-threaded Java db2fmp
processes. FENCED THREADSAFE routines, in contrast, perform better
because they can share a small number of JVMs.
- C and C++
- In general C and C++ routines perform better than other external
routine implementations and as well as SQL routines.
- To perform their best C and C++ routines should be compiled in
32-bit format if they will be deployed to a 32-bit DB2 instance and in 64-bit format if they will
be deployed to a 64-bit DB2 instance.
- COBOL
- In general COBOL performance is good, but COBOL is not a recommended
routine implementation.
|
Number of SQL statements within the routine |
- Routines should contain more than one SQL statement, otherwise
the overhead of routine invocation is not performance cost effective.
- Logic that must make several database queries, process intermediate
results, and ultimately return a subset of the data that was worked
with is the best logic for routine encapsulation. Complex data mining,
and large updates requiring lookups of related data are examples of
this type of logic. Heavy SQL processing is done on the database server
and only the smaller data result set is passed back to the caller.
|
Complexity of SQL statements within the routine |
- It makes good sense to include very complex queries within your
routines so that you capitalize on the greater memory and performance
capabilities of the database server.
- Do not worry about the SQL statements being overly complex.
|
Static or dynamic SQL execution within routines |
- In general static SQL performs better than dynamic SQL. In routines
there are no additional differences when you use static or dynamic
SQL.
|
Number of parameters to routines |
- Minimizing the number of parameters to routines can improve routine
performance as this minimizes the number of buffers to be passed between
the routine and routine invoker.
|
Data types of routine parameters |
- You can improve the performance of routines by using VARCHAR parameters
instead of CHAR parameters in the routine definition. Using VARCHAR
data types instead of CHAR data types prevents DB2 from padding parameters with spaces before
passing the parameter and decreases the amount of time required to
transmit the parameter across a network.
For example, if your client
application passes the string "A SHORT STRING" to a routine that expects
a CHAR(200) parameter, DB2 has
to pad the parameter with 186 spaces, null-terminate the string,
then send the entire 200 character string and null-terminator across
the network to the routine.
In comparison, passing the same
string, "A SHORT STRING", to a routine that
expects a VARCHAR(200) parameter results in DB2 simply passing the 14 character string and
a null terminator across the network.
|
Initialization of parameters to routines |
- It is a good idea to always initialize input parameters to routines,
particularly if the input routine parameter values are null. For
null value routine parameters, a shorter or empty buffer can be passed
to the routine instead of a full sized buffer, which can improve performance.
|
Number of local variables in routines |
- Minimizing the number of local variables declared within a routine
can improve performance by minimizing the number of SQL statements
executed within the routine.
- In general aim to use as few variables as possible. Re-use variables
if this will not be semantically confusing.
|
Initialization of local variables in routines |
- If possible, it is a good practice to initialize multiple local
variables within a single SQL statement as this saves on the total
SQL execution time for the routine.
|
Number of result sets returned by procedures |
- If you can reduce the number of result sets returned by a routine
you can improve routine performance.
|
Size of result sets returned by routines |
- Make sure that for each result set returned by a routine, the
query defining the result filters the columns returned and the number
of rows returned as much as possible. Returning unnecessary columns
or rows of data is not efficient and can result in sub-optimal routine
performance.
|
Efficiency of logic within routines |
- As with any application, the performance of a routine can be limited
by a poorly implemented algorithm. Aim to be as efficient as possible
when programming routines and apply generally recommended coding best
practices as much as possible.
- Analyze your SQL and wherever possible reduce your query to its
simplest form. This can often be done by using CASE expressions instead
of CASE statements or by collapsing multiple SQL statements into a
single statement that uses a CASE expression as a switch.
|
Run-time mode of routine (FENCED or NOT FENCED clause specification) |
- NOT FENCED clause usage:
-
- In general, creating your routine with the NOT FENCED clause,
which makes it runs in the same process as the DB2 database manager, is preferable over creating
it with the FENCED clause, which makes it run in a special DB2 process outside of the engine's
address space.
- While you can expect improved routine performance when running
routines as not fenced, user code in unfenced routines can accidentally
or maliciously corrupt the database or damage the database control
structures. You should only use the NOT FENCED clause when you need
to maximize performance benefits, and if you deem the routine to be
secure. (For information on assessing and mitigating the risks of
registering C/C++ routines as NOT FENCED, refer to Security of routines . If the routine
is not safe enough to run in the database manager's process, use the
FENCED clause when creating the routine. To limit the creation and
running of potentially unsafe code, DB2 requires
that a user have a special privilege, CREATE_NOT_FENCED_ROUTINE in
order to create NOT FENCED routines.
- If an abnormal termination occurs while you are running a NOT
FENCED routine, the database manager will attempt an appropriate recovery
if the routine is registered as NO SQL. However, for routines not
defined as NO SQL, the database manager will fail.
- NOT FENCED routines must be precompiled with the WCHARTYPE NOCONVERT
option if the routine uses GRAPHIC or DBCLOB data.
|
Run-time mode of routine (FENCED or NOT FENCED clause specification) |
- FENCED THREADSAFE clause usage
-
- Routines created with the FENCED THREADSAFE clause run in the
same process as other routines. More specifically, non-Java routines
share one process, while Java(TM) routines share another process,
separate from routines written in other languages. This separation
protects Java routines from
the potentially more error prone routines written in other languages.
Also, the process for Java routines
contains a JVM, which incurs a high memory cost and is not used by
other routine types. Multiple invocations of FENCED THREADSAFE routines
share resources, and therefore incur less system overhead than FENCED
NOT THREADSAFE routines, which each run in their own dedicated process.
- If you feel your routine is safe enough to run in the same process
as other routines, use the THREADSAFE clause when registering it.
As with NOT FENCED routines, information on assessing and mitigating
the risks of registering C/C++ routines as FENCED THREADSAFE is in
the topic, "Security considerations for routines".
- If a FENCED THREADSAFE routine abnormally ends, only the thread
running this routine is terminated. Other routines in the process
continue running. However, the failure that caused this thread to
abnormally end can adversely affect other routine threads in the process,
causing them to trap, hang, or have damaged data. After one thread
abends, the process is no longer used for new routine invocations.
Once all the active users complete their jobs in this process, it
is terminated.
- When you register Java routines,
they are deemed THREADSAFE unless you indicate otherwise. All other
LANGUAGE types are NOT THREADSAFE by default. Routines using LANGUAGE
OLE and OLE DB cannot be specified as THREADSAFE.
- NOT FENCED routines must be THREADSAFE. It is not possible to
register a routine as NOT FENCED NOT THREADSAFE (SQLCODE -104).
- Users on UNIX(R) can see their Java and
C THREADSAFE processes by looking for db2fmp (Java) or db2fmp (C).
|
Run-time mode of routine (FENCED or NOT FENCED clause specification) |
- FENCED NOT THREADSAFE mode
-
- FENCED NOT THREADSAFE routines each run in their own dedicated
process. If you are running numerous routines, this can have a detrimental
effect on database system performance. If the routine is not safe
enough to run in the same process as other routines, use the NOT THREADSAFE
clause when registering the routine.
- On UNIX, NOT THREADSAFE
processes appear as db2fmp (pid) (where pid is the process id of the
agent using the fenced mode process) or as db2fmp (idle) for a pooled
NOT THREADSAFE db2fmp.
|
Level of SQL access in routine: NO SQL, CONTAINS SQL, READS
SQL DATA, MODIFIES SQL DATA |
- Routines that are created with a lower level of SQL access clause
will perform better than routines created with a higher level of SQL
access clause. Therefore you should declare your routines with the
most restrictive level of SQL access clause. For example, if your
routine only reads SQL data, do not create it with the MODIFIES SQL
DATA clause, but rather create it with the more restrictive READS
SQL DATA clause.
|
Determinism of routine (DETERMINISTIC or NOT DETERMINISTIC
clause specification) |
- Declaring a routine with the DETERMINISTIC or NOT DETERMINISTIC
clause has no impact on routine performance.
|
Number and complexity of external actions made by routine (EXTERNAL
ACTION clause specification) |
- Depending on the number of external actions and the complexity
of external actions performed by an external routine, routine performance
can be hindered. Factors that contribute to this are network traffic,
access to files for writing or reading, the time required to execute
the external action, and the risk associated with hangs in external
action code or behaviors.
|
Routine invocation when input parameters are null (CALLED ON
NULL INPUT clause specification) |
- If receiving null input parameter values results in no logic being
executed and an immediate return by the routine, you can modify your
routine so that it is not fully invoked when null input parameter
values are detected. To create a routine that ends invocation early
if routine input parameters are received, create the routine and specify
the CALLED ON NULL INPUT clause.
|
Procedure parameters of type XML |
- The passing of parameters of data type XML is significantly less
efficient in external procedures implemented in either the C or JAVA
programming language than in SQL procedures. When passing one or
more parameters of data type XML, consider using SQL procedures instead
of external procedures.
- XML data is materialized when passed to stored procedures as IN,
OUT, or INOUT parameters. If you are using Java stored procedures, the heap size (JAVA_HEAP_SZ
configuration parameter) might need to be increased based on the quantity
and size of XML arguments, and the number of external stored procedures
that are being executed concurrently.
|