Guidelines for restricting SELECT statements
The optimizer assumes that an application must retrieve all of the rows that are identified by a SELECT statement. This assumption is most appropriate in online transaction processing (OLTP) and batch environments.
However, in browse
applications, queries often define a
large potential answer set, but they retrieve only the first few rows,
usually the number of rows that are required for a particular display
format.
- Use the FOR UPDATE clause to specify the columns that could be updated by a subsequent positioned UPDATE statement.
- Use the FOR READ or FETCH ONLY clause to make the returned columns read-only.
- Use the OPTIMIZE FOR n ROWS clause to give priority to retrieving the first n rows from the full result set.
- Use the FETCH FIRST n ROWS ONLY clause to retrieve only a specified number of rows.
- Use the DECLARE CURSOR WITH HOLD statement to retrieve rows one at a time.
The following sections describe the performance advantages of each method.
FOR UPDATE clause
The FOR UPDATE clause limits the result set by including only those columns that can be updated by a subsequent positioned UPDATE statement. If you specify the FOR UPDATE clause without column names, all columns that can be updated in the table or view are included. If you specify column names, each name must be unqualified and must identify a column of the table or view.
- The cursor that is associated with the SELECT statement cannot be deleted
- At least one of the selected columns is a column that cannot be updated in a catalog table and that has not been excluded in the FOR UPDATE clause.
In CLI applications, you can use the CLI connection attribute SQL_ATTR_ACCESS_MODE for the same purpose.
FOR READ or FETCH ONLY clause
The FOR READ ONLY clause or the FOR FETCH ONLY clause ensures that read-only results are returned. For result tables where updates and deletions are allowed, specifying the FOR READ ONLY clause can improve the performance of fetch operations if the database manager can retrieve blocks of data instead of using exclusive locks. Do not specify the FOR READ ONLY clause in queries that are used in positioned UPDATE or DELETE statements.
In CLI applications, you can use the CLI connection attribute SQL_ATTR_ACCESS_MODE for the same purpose.
OPTIMIZE FOR n ROWS clause
The OPTIMIZE FOR clause declares the intent to retrieve only a subset of the result or to give priority to retrieving only the first few rows. The optimizer can then choose access plans that minimize the response time for retrieving the first few rows. In addition, the number of rows that are sent to the client as a single block are limited by the value of n. Thus the OPTIMIZE FOR clause affects how the server retrieves qualifying rows from the database, and how it returns those rows to the client.
select lastname, firstnme, empno, salary
from employee
order by salary desc
select lastname, firstnme, empno, salary
from employee
order by salary desc
optimize for 20 rows
In this case, the optimizer will
likely choose to use the SALARY index directly, because only the 20
employees with the highest salaries are retrieved. Regardless of how
many rows might be blocked, a block of rows is returned to the client
every twenty rows.- Join sequences with composite inner tables are less likely, because they require a temporary table.
- The join method might change. A nested loop join is the most likely choice, because it has low overhead cost and is usually more efficient when retrieving a few rows.
- An index that matches the ORDER BY clause is more likely, because no sort is required for the ORDER BY.
- List prefetching is less likely, because this access method requires a sort.
- Sequential prefetching is less likely, because only a small number of rows is required.
- In a join query, the table with columns in the ORDER BY clause is likely to be chosen as the outer table if an index on the outer table provides the ordering that is needed for the ORDER BY clause.
Although the OPTIMIZE FOR clause applies to all optimization levels, it works best for optimization class 3 and higher, because classes lower than 3 use the greedy join enumeration search strategy. This method sometimes results in access plans for multi-table joins that do not lend themselves to quick retrieval of the first few rows.
If a packaged application uses the call-level interface (CLI or ODBC), you can use the OPTIMIZEFORNROWS keyword in the db2cli.ini configuration file to have CLI automatically append an OPTIMIZE FOR clause to the end of each query statement.
When data is selected from nicknames, results can vary depending on data source support. If the data source that is referenced by a nickname supports the OPTIMIZE FOR clause, and the Db2® optimizer pushes the entire query down to the data source, then the clause is generated in the remote SQL that is sent to the data source. If the data source does not support this clause, or if the optimizer decides that the least costly plan is local execution, the OPTIMIZE FOR clause is applied locally. In this case, the Db2 optimizer prefers access plans that minimize the response time for retrieving the first few rows of a query, but the options that are available to the optimizer for generating plans are slightly limited, and performance gains from the OPTIMIZE FOR clause might be negligible.
If the OPTIMIZE FOR clause and the FETCH FIRST clause are both specified, the lower of the two n values affects the communications buffer size. The two values are considered independent of each other for optimization purposes.
FETCH FIRST n ROWS ONLY clause
The FETCH FIRST n ROWS ONLY clause sets the maximum number of rows that can be retrieved. Limiting the result table to the first several rows can improve performance. Only n rows are retrieved, regardless of the number of rows that the result set might otherwise contain.
If the FETCH FIRST clause and the OPTIMIZE FOR clause are both specified, the lower of the two n values affects the communications buffer size. The two values are considered independent of each other for optimization purposes.
DECLARE CURSOR WITH HOLD statement
When you declare a cursor using a DECLARE CURSOR statement that includes the WITH HOLD clause, open cursors remain open when the transaction commits, and all locks are released, except those locks that protect the current cursor position. If the transaction is rolled back, all open cursors are closed, all locks are released, and any LOB locators are freed.
In CLI applications,
you can use the CLI connection
attribute SQL_ATTR_CURSOR_HOLD for the same purpose. If a packaged
application uses the call level interface (CLI or
ODBC), use the CURSORHOLD keyword in the db2cli.ini
configuration
file to have CLI automatically
assume the WITH HOLD clause for every declared cursor.