Db2 Standards, Tips & Guidelines
Db2 Standards, Tips & Guidelines
Db2 Standards, Tips & Guidelines
• Introduction
• SQL General Information
• Using SQL
• SQL Error Handling
• DB2 Tools & Environment
• Design Considerations
• Focus Considerations
• DB2 Program Development Procedures
• Internal DB2 Processing Considerations
A. INTRODUCTION
In order to standardize DB2 development and improve maintainability, sample DB2 programs and program
shells have been created for both online and batch environments. Before beginning a new program, it
would be helpful to review both the shell and the sample program. Ideally, either the shell or the sample
program will serve as a starting point for creating new programs. The shells and sample programs are found
in DS.TEST.PANVALET as follows:
Online:
Batch:
Other Components:
The shells, sample programs, and common modules have been made available to give application
programmers a starting point when creating DB2 programs. They were meant to enhance, not replace the
following standards. Please refer to the following sections for more detail on programming with DB2. If
you still can't find an answer, contact the DBA team for assistance.
Sample tables and a sample application program that accesses these tables were also shipped with DB2.
Copies of the sample program in several different languages can be found in Appendix B of the DB2
Application Programming and SQL Guide. The programs are also stored in library 'DS.PANVALET'
accessible through ISPF. The Cobol batch program is 'DB2COBOL'.
SQL is the language that will be used for all data definition, data manipulation, queries, and authorization
administration for all database functions. SQL is a set-processor, non-procedural, and non-navigational
language and consists of 3 components:
C. USING SQL
Multicolumn indexes
If a table has only multicolumn indexes, try to specify the high-level column in the WHERE clause of your
query. This results in an index scan with at least one matching column.
Use the same data types and lengths when comparing column values to host variables or literals. This
eliminates the need for data conversion and allows for the use of an index. For example, comparing a
column defined as CHAR(6) to a field which is CHAR(4) or CHAR(7) will cause data conversion and
should be avoided at all costs. The easiest way to ensure datatype consistency is to use the DCLGEN fields
whenever possible.
•
Both operands must be of the same data type (ie, both dates or both
times)
Example: CURRENT DATE - 1 MONTH or CURRENT DATE + 1 DAY
•
If one operand is a timestamp, the other operand can be a time or a
date, but not a timestamp.
Example: TIMESTAMP + 1 DAY or TIMESTAMP - 24 HOURS
Joins will give the DB2 optimizer more options for data access than a subquery.
Use of DCLGEN
Create the table layout ('include' member) by executing a DCLGEN in SPUFI. The DCLGEN includes a
DECLARE statement and a cobol layout for the table.
Move the member from the default library to DS.TEST.PANVALET and use the standard
'++INCLUDE' to bring the definition into your program.
(Do not use the 'EXEC SQL INCLUDE' statement as seen in some sample programs.)
It is more efficient to use the SQL built-in functions (AVG, COUNT, MAX, MIN, SUM) than the
application program perform these functions (before using these, be sure to zero the variable you select
into and check for SQLCODE 0, -305, or other).
About Concurrency
Typically, batch programs are executed in the "batch window" which is a given time frame where online
applications will not be accessing the tables being updated. The LOCK TABLE statement would frequently
be used in the batch window since it provides the least amount of DB2 locking overhead. Care must be
taken as indicated above that online programs will not be attempting to utilize this table space, or that
concurrent batch activity is not being processed.
DB2 provides the ability to execute batch table updates in concurrence with CICS or other batch jobs.
However, there is a performance cost for such an activity. Either the job is quickly run or frequent
COMMIT commands would be needed (see following section).
NOTE: This concurrency feature is quite attractive, and makes batch a better alternative to background
CICS processing in most cases.
About COMMITting
It is important to issue COMMIT commands in batch programs for two reasons; it will improve recovery
time by reducing the amount of work that has to backed out and redone in the case of an abnormal
termination, and it will free locks used by the batch job allowing more concurrency.
A checkpoint/restart routine must be established for batch programs which will store all relevant
information needed to restart the program in a separate DB2 table followed by a COMMIT call. When the
program runs or reruns, an initialization routine will read the DB2 restart table to obtain a starting point. It
will be your responsibility to recover any non-DB2 resources that are updated by the program.
The frequency at which checkpoints should be taken will vary from application to application. There are a
number of considerations for selecting the commit frequency. If the batch program is accessing tables that
are also being accessed by online transactions, you should checkpoint very frequently. If the data accessed
by the batch program is not used concurrently by online transactions, the checkpoint interval should be
such that the restart time is acceptable.
Checkpoint/Restart
Once a COMMIT is issued in the batch program, the program must be written to support a restart at the
point of the COMMIT. This would include repositioning the cursor, repositioning in an input transaction
file, and handling the output files, including reports, so that there will not be any lost data.
It is generally advisable not to write to a non-DB2 file at the same time you are updating a DB2 database. If
an output file must be written DB2 table(s) could be used to contain pertinent information for a later
process. If the output file is too large for DB2 then the program must insure that all data information is
written to the file at the time of the COMMIT (externalize the output records). This can be accomplished
through the MVS checkpoint/restart facility, or by closing and then reopening the files (see Section H for
details and examples of checkpoint/restart).
• Every sql call in your program should check the sqlcode returned by the
call. If this sqlcode is a 'bad' return code, then you should perform S9999-
sql-error. When checking the sqlcode and it is determined to be a bad
sqlcode, the variables in the ws-error-area should be set with the proper
program and DB2 values:
• When calling DSNTIAR from a batch program, the batch program will
need to be compiled with the DYNAM parameter.
SQLCA
Always include the SQLCA include member in your application program.
Error Checking
Always check the SQL return code available in the SQLCODE field after every SQL statement:
General checking:
DB2 Deadlocks
The use of the DB2 locking scheme may lead to a problem called deadlocking. This situation may arise
when two programs are attempting to update tables that have been previously locked by the other. In a
deadlock situation, DB2 arbitrarily selects a "winner" and a "loser". The "loser" will receive SQL error
code -911 or -913 and the current processing is rolled back. As a precautionary step it is important to update
all tables in related applications in the same sequence.
DB2I is an interactive tool which allows one to invoke DB2 utilities, prepare programs for execution and
issue DB2 commands. DB2I provides an option called SPUFI which facilitates the development and testing
of Structured Query Language (SQL) statements. To invoke DB2I follow the steps below:
• Logon to TSO
• Select Option DB2 at the ISPF Primary Menu by entering 'D' at the
command line.
The first time you invoke DB2I default settings must be established via Option "D", DB2I Defaults, from
the DB2I Primary Option Menu. This will display the DB2I Primary Option Menu:
DB2I allows you to execute several processes interactively, however, standard JCL procedures will also be
available to execute processes such as performing a DCLGEN, executing, the precompiler, compiler, and
linkage editor, and executing the BIND in batch mode.
This section will discuss the recommended parameters to use for DB2I and SPUFI. DB2I Defaults are
selected from Option D on the DB2I Primary Option Menu. The subsystem identifier parameter is set on
this screen. To select the TEST DB2 subsystem, enter "DBT1" on line 1, "DB2 Name". The production
DB2 susbystem can be accessed for authorized users only by entering "DBP1".
To change spufi defaults, select option 1 (SPUFI) from the main DB2I menu. Current SPUFI defaults are
updatable from a selection panel that is displayed when a "Y" is entered on the Option 5 line, "Change
Defaults" , from the SPUFI panel. It is important to select ISOLATION LEVEL ==> CS (CURSOR
STABILITY) to minimize the time a read-only page lock is held.
F. DESIGN CONSIDERATIONS
1. Indexes
Index Usage
Indexes are used in a WHERE clause with the following predicate types:
* column = value
* column is null
* column > value
* column < value
* column >= value
* column <= value
* column BETWEEN value1 and value2
* column LIKE 'char%'
* column IN list
Indexes are NOT used in WHERE clauses with the following predicates:
Standards
Avoid the use of LIKE predicates with host variables or predicates beginning with % or _
They may prevent DB2 from using indexes that might be defined on a column to limit the number of rows
scanned.
Guidelines
When every page in the tablespace is retrieved, a tablespace scan is more efficient.
Always fully qualify the search criterion that you specify in your SQL statement.
Always specify the same data type, precision, and scale when comparing column values against host
variables and literals.
G. Focus Considerations
1. Background
The primary tool for ad hoc reporting against DB2 data will be Focus. While the Focus syntax is the same
regardless of the data structure accessed (VSAM, sequential files, DB2 tables, etc.), there are special
considerations when accessing DB2 data. It is advisable for the query writer to understand the appropriate
coding techniques for writing efficient queries which will provide accurate information.
A Master File Description (MFD) is required for each table and view which will be accessed via Focus
queries. This can be generated by a member of Information Access Group (IAG) staff using the Focus
utility 'Auto-DB2'. The utility uses the DB2 catalog tables to generate the Focus code. This is a convenient
way to create an MFD and also ensure that all table/view names and column names exactly match the DB2
objects. This utility will be used both in test and production
An Access File Description (AFD) is also required for each table and view to be accessed via Focus
queries. An AFD makes the connection between the table name, as used in a Focus query, and the actual,
fully-qualified DB2 table name (owner.tablename). This will also be generated by Auto-DB2. Because the
fully-qualified name will indicate the subsystem by the owner name (TESTDBA for test, PRODDBA for
production), it must agree with the subsystem id being accessed (see item 4 below).
It is possible to access data in the DB2 test subsystem (DBT1) as well as data in the production subsystem
(DBP1). A Focus query will attempt to access data in the production subsystem by default. However, if a
user wishes to 'test' a query against a smaller table - such as a test table, OR if the query must access new
tables not yet implemented in production, the following conditions must be met:
• An MFD and AFD for each table and view must exist in the test libraries
(FOCUS.INFO. MASTER. TEST for MFD's and
FOCUS.ACCESS.MASTER.TEST for AFD's)
• The user must specify the test subsystem (to override the default) using this
command as the first statement in the query: TSO SQL SET SSID DBT1
• The user must select 'DBT1' from the file screen (to indicate usage of the
test library copy of the MFD and AFD).
Selected, representative Focus queries will be used to test access and provide benchmark statistics for test
DB2 tables which will implemented in the Information Center.
1. Compile Procedures
Compile Procedures
2. BIND Considerations
Background
To access DB2 data, an SQL statement requires an access path. For dynamic SQL, such as statements
issued through SPUFI, DB2 determines the access path when the statement executes. For statements that do
not execute often, this method is usually acceptable. However, an application typically runs the same SQL
statements repeatedly. In this case, determining the access path at run time wastes system resources,
because the system must determine the same path repeatedly. To conserve your system resources, use static
SQL. Access paths for static SQL are determined only at BIND or REBIND time.
When a DB2 program is compiled, it produces a load module and a DBRM (Database Request Module)
containing the executable SQL. For this program to be executed, the DBRM must either be bound into a
package or directly into plan. A package can contain only 1 DBRM, but a plan can include many DBRMs
and/or packages. To run the program, you must specify a program and it's plan.
Depending upon how you design your DB2 application, you might bind all your DBRMs in one operation,
creating only a single application plan. Or, you might bind some or all of your DBRMs into separate
packages in separate operations. After that, you must still bind the entire application as a single plan, listing
the included packages or collections and binding any DBRMs not already bound into packages. Regardless
of what the plan contains, you must bind a plan before the application can run.
Incremental Development of Your Program: Binding packages into package collections allows you to add
packages to an existing application plan without having to bind the entire plan again. A collection is a group
of associated packages. If you include a collection name in the package list when you bind a plan, any
package in the collection becomes available to the plan. The collection can even be empty when you first
bind the plan. Later, you can add packages to the collection, and drop or replace existing packages, without
binding the plan again.
Versioning: Maintaining several versions of a plan without using packages requires a separate plan for each
version, and therefore separate plan names and RUN commands. Isolating separate versions of a program
into packages requires only one plan and helps to simplify program migration and fallback. For example,
you can maintain separate development, test, and production levels of a program by binding each level of
the program as a separate version of a package, all within a single plan.
For plans which are bound with only one DBRM, packages don't offer any advantage. However, for plans
that use multiple DBRMs, it is sometimes better to bind each DBRM into a package and then bind the
packages into the plan. This feature will be especially valuable for CICS applications where concurrency is
more of an issue.
Bind Standards
• The program, DBRM, and plan names should always be the same.
• The program should use unqualified table names to allow the 'OWNER'
parameter of the bind to supply the qualifier ('TESTDBA' or 'PRODDBA').
This will require the programmer to edit the sql 'declare table' statement
• Always BIND the plan again using the Replace option following a DB2
recompile.
• DBA approval will be required in order to use the Repeatable Read option
for the Isolation level BIND parameter. It is best to use Cursor Stability.
Guidelines
The parameters for a program named 'AA0100BB' to be bound in test for the first time would be as
follows:
DSN SYSTEM(DBT1)
BIND PLAN(AA0100BB) MEMBER(AA0100BB) -
LIBRARY ('DBT1.DB2.DBRMLIB') -
OWNER(TESTDBA) -
ACTION(ADD) -
RETAIN -
ISOLATION(CS) -
VALIDATE(BIND) -
RELEASE(COMMIT)
Subsequent executions of the bind would specify 'ACTION(REPL)' to replace the previous plan.
The parameters for a program named 'AA0100BB' to be bound in production for the first time would be as
follows:
DSN SYSTEM(DBP1)
BIND PLAN(AA0100BB) MEMBER(AA0100BB) -
LIBRARY ('DBP1.DB2.DBRMLIB') -
OWNER(PRODDBA) -
ACTION(ADD) -
RETAIN -
ISOLATION(CS) -
VALIDATE(BIND) -
RELEASE(COMMIT)
Subsequent executions of the bind would specify 'ACTION(REPL)' to replace the previous plan.
Information
All plans which access a DB2 object that has been dropped will be marked as invalid. DB2 will
automatically rebind the plans the next time they execute, however, for performance reasons it is better to
manually rebind invalid plans.
3. Using Explain
The EXPLAIN statement and the EXPLAIN option of the BIND or REBIND commands can be used to get
information about the access paths used by DB2. The results of EXPLAIN are stored in a table that must
first be created by the plan owner or user that executes the EXPLAIN statement. Production information
will be stored in a table named "userid.PLAN.TABLE".
A standard query containing the SQL statements needed to create the plan.table can be copied from the
following member: "DBT1.DB2.SQLLIB(EXPLAIN)".
When the EXPLAIN option of the BIND command is selected, one or more rows for each explainable
statement in the plan will be stored in userid.PLAN.TABLE. The EXPLAIN statement stores information
about a single explainable statement. The data collected canthen be reviewed by querying the following
columns in this table. Some of the important fields are described below:
1. I - index
2. I1 - one-fetch index scan
3. R - tablespace scan (sequential)
4. N - index, for IN predicate
5. M - multiple indexes used
6. MX - multiple scans of one index
INDEXONLY Is this step fully serviced by index only or will data be accessed? (Y/N)
SORTN_xxxx Sort to create the "new" (input) table to this step? (Y/N)
(want to see "Y" for most efficient access)
1. S - shared
2. X - exclusive
3. IS - shared page locks
4. IX - exclusive page locks
1. Thread Utilization
It is important to minimize the times a thread is allocated to an application to improve system throughput.
Minimize allocation overhead in high-volume, repetitive transactions by specifying the ACQUIRE and
RELEASE BIND parameters and reusing the thread.
Information
The thread concept is how applications access DB2 data. A thread is responsible for the following:
identifies the user, allocates DB2 resources, and executes user requests.
Information
The lock size is determined by the creator of the tablespace. A DB2 object may be locked at the page, table
(segmented tablespaces), or tablespace level. The lock type is determined by the type of statement that is
executed. For example, a SELECT or FETCH statement from a read-only cursor uses a shared lock; a
cursor with a FOR UPDATE OF clause uses an update lock; and an exclusive lock is used when an
UPDATE, INSERT, OR DELETE statement is executed. The lock duration is determined by the isolation
level specified in the BIND step or in SPUFI. Lock escalation is used by DB2 to increase the size of a lock
for performance reasons.
End Of Document