Professional Documents
Culture Documents
SQR Performance Tuning PDF
SQR Performance Tuning PDF
SQR, a specialized language for database processing and reporting and performance considerations are an
important aspect of application development. This papers examines some of the issues that affect the
performance of SQR programs. It also describes certain SQR capabilities that can help you write high-
performance programs.
This paper focuses on SQR tools for simplifying SQL statements and reducing the number of SQL
executions. There are several techniques, including:
• Simplify a complex select paragraph.
• Use LOAD-LOOKUP to simplify joins.
• Improve SQL performance with dynamic SQL.
• Examine SQL cursor status.
• Avoid temporary database tables.
• Create multiple reports in one pass.
• Tune SQR numerics.
• Compile SQR programs and use SQR Execute.
• Set processing limits.
• Buffer fetched rows.
• Run programs on the database server.
In this code example, the LOAD-LOOKUP command loads an array with the EMPLOYEE_ID and
EMPLOYEE_NAME columns from the EMPNAME table. The lookup array is named NAMES. The
EMPLOYEE_ID column is the key and the EMPLOYEE_NAME column is the return value. In the select
paragraph, a LOOKUP on the NAMES array retrieves the EMPLOYEE_NAME for each
EMPLOYEE_ID. This technique eliminates the need to join the EMPNAME table in the select.
If the JOB and EMPNAME tables were joined in the select (without LOAD-LOOKUP), the code would
look like this:
begin-select
BUSINESS_UNIT (+1,1)
JOB.EMPLOYEE_IDproduct_code
EMPLOYEE_NAME (,15)
from JOB, EMPNAME
where JOB.EMPLOYEE_ID = EMPNAME.EMPLOYEE_ID
end-select
Whether a database join or LOAD-LOOKUP is faster depends on the program. LOAD-LOOKUP
improves performance when:
• It is used with multiple select paragraphs.
• It keeps the number of tables being joined from exceeding three or four.
• The number of entries in the LOAD-LOOKUP table is small compared to the number of rows in
the select, and they are used often.
• Most entries in the LOAD-LOOKUP table are used.
Note. You can concatenate columns if you want RETURN_VALUE to return more than one column. The
concatenation symbol is database specific.
begin-select
BUSINESS_UNIT
from JOB, LOCATION_TBL
where JOB.BUSINESS_UNIT = LOCATION_TBL.BUSINESS_UNIT
and ($state = 'CA' and EFF_DATE > $start_date
or $state != 'CA' and TRANSFER_DATE > $start_date)
end-select
However, the same work can be done with a simpler select. For example, if $state is ‘CA,’ the following
select works:
begin-select
BUSINESS_UNIT
from JOB, LOCATION_TBL
where JOB.BUSINESS_UNIT = LOCATION_TBL.BUSINESS_UNIT
and EFF_DATE > $start_date
end-select
Dynamic SQL enables you to check the value of $state and create the simpler condition:
if $state = 'CA'
let $datecol = 'EFF_DATE'
else
let $datecol = 'TRANSFER_DATE'
end-if
begin-select
BUSINESS_UNIT
from JOB, LOCATION_TBL
where JOB.BUSINESS_UNIT = LOCATION_TBL.BUSINESS_UNIT
and [$datecol] > $start_date
end-select
The [$datecol] substitution variable substitutes the name of the column to be compared with $state_date.
The select is simpler and no longer uses an OR operator. In most cases, this use of dynamic SQL
improves performance.
Because SQR programs select and manipulate data from a SQL database, it is helpful to understand how
SQR processes SQL statements and queries.
SQR programs can perform multiple SQL statements. Moreover, the same SQL statement can be run
multiple times.
When a program runs, a pool of SQL statement handles—called cursors—is maintained. A cursor is a
storage location for one SQL statement; for example, SELECT, INSERT, or UPDATE. Every SQL
statement uses a cursor for processing. A cursor holds the context for the execution of a SQL statement.
The cursor pool contains 30 cursors, and its size cannot be changed. When a SQL statement is rerun, its
cursor can be immediately reused if it is still in the cursor pool. When an SQR program runs more than 30
different SQL statement, cursors in the pool are reassigned.
To examine how cursors are managed, use the -S command-line flag. This flag displays cursor status
information at the end of a run.
The following information appears for each cursor:
Cursor #nn:
SQL = <SQL statement>
Compiles = nn
Executes = nn
Rows = nn
The listing also includes the number of compiles, which vary according to the database and the
complexity of the query. With Oracle, for example, a simple query is compiled only once. With
SYBASE, a SQL statement is compiled before it is first run and recompiled for the purpose of validation
during the SQR compile phase. Therefore, you may see two compiles for a SQL statement. Later when
the SQL is rerun, if its cursor is found in the cursor pool, it can proceed without recompiling.
Avoiding Temporary Database Tables
Programs often use temporary database tables to hold intermediate results. Creating, updating, and
deleting database temporary tables is a very resource-consuming task, however, and can hurt your
program’s performance. SQR provides two alternatives to using temporary database tables.
The first alternative is to store intermediate results in an SQR array. The second is to store intermediate
results in a local flat file. Both techniques can bring about a significant performance gain. You can use
the SQR language to manipulate data stored in an array or a flat file.
These two methods are explained and demonstrated in the following sections. Methods for sorting data in
SQR arrays or flat files are also explained.
The following code example retrieves records, prints them, and saves them into an array named
ADDRESS_DETAILS_ARRAY:
The ADDRESS_DETAILS_ARRAY array has four fields that correspond to the four columns that are
selected from the ADDRESS table, and it can hold up to 1,000 rows. If the ADDRESS table had more
than 1,000 rows, it would be necessary to create a larger array.
The select paragraph prints the data. The PUT command then stores the data in the array. You could use
the LET command to assign values to array fields, however the PUT command performs the same work,
with fewer lines of code. With PUT, you can assign all four fields in one command.
The #counter variable serves as the array subscript. It starts with zero and maintains the subscript of the
next available entry. At the end of the select paragraph, the value of #counter is the number of records in
the array.
The next code example retrieves the data from ADDRESS_DETAILS_ARRAY and prints it:
let #i = 0
while #i < #counter
get &ADDRESSLINE1 &ADDRESSLINE2 &PINCODE &PHONE from ADDRESS_DETAILS_ARRAY(#i)
print $ADDRESSLINE1 (,1)
print $ADDRESSLINE2 (,7)
print $PINCODE (,24)
print $PHONE (,55)
position (+1)
add 1 to #i
end-while
In this code example, #i goes from 0 to #counter-1. The fields from each record are moved into the
corresponding variables: $ADDRESSLINE1, $ADDRESSLINE2, $PINCODE and $PHONE. These values
are then printed.
The OPEN command opens the file for writing and assigns it file number 1. You can open as many as 12
files in one SQR program. The file is set to support records of varying lengths with a maximum of 80
bytes (characters). For this example, you can also use fixed-length records.
As the program selects records from the database and prints them, it writes them to cust.dat:
write 1 from &ADDRESSLINE1:30 &ADDRESSLINE2:30 &PINCODE:6 &PHONE:10
The WRITE command writes the four columns into file number 1—the currently open cust.dat. It writes
the name first, which makes it easier to sort the file by name. The program writes fixed-length fields. For
example, &ADDRESSLINE1:30 specifies that the name column uses exactly 30 characters. If the actual
name is shorter, it is padded with blanks. When the program has finished writing data to the file, it closes
the file by using the CLOSE command.
The sort cust.dat > cust2.datis command sent to the UNIX system. It invokes the UNIX sort command to
sort cust.dat and direct the output to cust2.dat. The completion status is saved in #status; a status of 0
indicates success. Because name is at the beginning of each record, the file is sorted by name.
Next, we open cust2.dat for reading. The following command reads one record from the file and places
the first 30 characters in $ADDRESSLINE1:
The next two characters are placed in $PINCODE and so on. When the end of the file is encountered, the
#end-file reserved variable is automatically set to 1 (true). The program checks for #end-file and breaks
out of the loop when the end of the file is reached. Finally, the program closes the file by using the
CLOSE command.
To reduce network traffic and improve performance, run SQR programs directly on the database server
machine. The SQR server is available on many server platforms including Windows NT and
UNIX/Linux.
Structured Programming
A technique for organizing and coding computer programs in which a hierarch of modules issued,
each having a single entry and a single exit point, and in which control is passed downward through
the structure without unconditional branches to higher levels of the structure.
Structured programming is often associated with a top-down approach to design. In this way
designers map out the large scale structure of a program in terms of smaller operations, implement
and test the smaller operations, and then tie them together into a whole program.
• Pseudo-Code
o Flowchart the program logic
o Research and ask a few questions:
How much data will be pulled? Will it be100 rows or 1000 rows?
How many rows will come from each table?
What kind of data will be pulled? Student Data? Setup Data?
What does the key structure look like for the tables being pulled?
Is this table the parent or the child?
How important is this table?
What fields will be needed from this table? Are they available somewhere else?
o Write SQL and test in SQL Plus before coding SQR
Summary
The following techniques can be used to improve the performance of your SQR programs:
• Simplify complex SELECT statements.
• Use LOAD-LOOKUP to simplify joins.
• Use dynamic SQL instead of a condition in a SELECT statement.
• Avoid using temporary database tables. Two alternatives to temporary
database tables are SQR arrays and flat files.
• Write programs that create multiple reports with one pass on the data.
• Use the most efficient numeric type for numeric variables (machine
floating point, decimal, or integer).
• Save compiled SQR programs and rerun them with SQR Execute.
• Adjust settings in the [Processing-Limits] section of SQR.INI or in a
startup file.
• Increase buffering of rows in SELECT statements with the -B flag.
• Execute programs on the database server machine.
• SQR Programming Principles