19 Influencing the Optimizer
Optimizer defaults are adequate for most operations, but not all.
In some cases you may have information unknown to the optimizer, or need to tune the optimizer for a specific type of statement or workload. In such cases, influencing the optimizer may provide better performance.
This chapter contains the following topics:
- Techniques for Influencing the Optimizer
You can influence the optimizer using several techniques, including SQL profiles, SQL Plan Management, initialization parameters, and hints. - Influencing the Optimizer with Initialization Parameters
This chapter explains which initialization parameters affect optimization, and how to set them. - Influencing the Optimizer with Hints
Optimizer hints are special comments in a SQL statement that pass instructions to the optimizer.
19.1 Techniques for Influencing the Optimizer
You can influence the optimizer using several techniques, including SQL profiles, SQL Plan Management, initialization parameters, and hints.
The following figure shows the principal techniques for influencing the optimizer.
Figure 19-1 Techniques for Influencing the Optimizer
![Description of Figure 19-1 follows Description of Figure 19-1 follows](img/tgsql_vm_014.png)
Description of "Figure 19-1 Techniques for Influencing the Optimizer"
The overlapping squares in the preceding diagram show that SQL plan management uses both initialization parameters and hints. SQL profiles also technically include hints.
Note:
A stored outline is a legacy technique that serve a similar purpose to SQL plan baselines.
You can use the following techniques to influence the optimizer:
Table 19-1 Optimizer Techniques
Technique | Description | To Learn More |
---|---|---|
Initialization parameters |
Parameters influence many types of optimizer behavior at the database instance and session level. |
|
Hints |
A hint is a commented instruction in a SQL statement. Hints control a wide range of behavior. |
|
|
This package updates and manages optimizer statistics. The more accurate the statistics, the better the optimizer estimates. This chapter does not cover |
|
SQL profiles |
A SQL profile is a database object that contains auxiliary statistics specific to a SQL statement. Conceptually, a SQL profile is to a SQL statement what a set of object-level statistics is to a table or index. A SQL profile can correct suboptimal optimizer estimates discovered during SQL tuning. |
|
SQL plan management and stored outlines |
SQL plan management is a preventative mechanism that enables the optimizer to automatically manage execution plans, ensuring that the database uses only known or verified plans. This chapter does not cover SQL plan management. |
In some cases, multiple techniques optimize the same behavior. For example, you can set optimizer goals using both initialization parameters and hints.
See Also:
"Migrating Stored Outlines to SQL Plan Baselines" to learn how to migrate stored outlines to SQL plan baselines
19.2 Influencing the Optimizer with Initialization Parameters
This chapter explains which initialization parameters affect optimization, and how to set them.
This section contains the following topics:
- About Optimizer Initialization Parameters
Oracle Database provides initialization parameters to influence various aspects of optimizer behavior, including cursor sharing, adaptive optimization, and the optimizer mode. - Enabling Optimizer Features
TheOPTIMIZER_FEATURES_ENABLE
initialization parameter (or hint) controls a set of optimizer-related features, depending on the database release. - Choosing an Optimizer Goal
The optimizer goal is the prioritization of resource usage by the optimizer. - Controlling Adaptive Optimization
In Oracle Database, adaptive query optimization is the process by which the optimizer adapts an execution plan based on statistics collected at run time.
19.2.1 About Optimizer Initialization Parameters
Oracle Database provides initialization parameters to influence various aspects of optimizer behavior, including cursor sharing, adaptive optimization, and the optimizer mode.
The following table lists some of the most important optimizer parameters.
Table 19-2 Initialization Parameters That Control Optimizer Behavior
Initialization Parameter | Description |
---|---|
APPROX_FOR_AGGREGATION |
Uses approximate query processing for all aggregation and analytic queries. Approximate processing is useful when you want to obtain faster query results and avoid writes to a temporary tablespaces. This optimizer uses a nondeterministic algorithm to make its estimations, which means that different queries can obtain different results. You can set this parameter to This parameter changes the optimizer environment. It does not force the optimizer to change the SQL text for an affected query, but it does force the optimizer to reparse the query and create a new child cursor. |
|
Replaces queries that contain This parameter changes the optimizer environment. It does not force the optimizer to change the SQL text for an affected query, but it does force the optimizer to reparse the query and create a new child cursor. |
APPROX_FOR_PERCENTILE |
Converts exact percentile functions to their approximate percentile function counterparts. Approximate percentile function queries are faster than their exact percentile function query counterparts, so they can be useful in situations where a tolerable amount of error is acceptable in order to obtain faster query results. Set to This parameter changes the optimizer environment. It does not force the optimizer to change the SQL text for an affected query, but it does force the optimizer to reparse the query and create a new child cursor. |
CURSOR_INVALIDATION |
Provides the default cursor invalidation level for DDL statements.
You can set this parameter at the |
|
Converts literal values in SQL statements to bind variables. Converting the values improves cursor sharing and can affect the execution plans of SQL statements. The optimizer generates the execution plan based on the presence of the bind variables and not the actual literal values. Set to |
|
Specifies the number of blocks that are read in a single I/O during a full table scan or index fast full scan. The optimizer uses the value of this parameter to calculate the cost of full table scans and index fast full scans. Larger values result in a lower cost for full table scans, which may result in the optimizer choosing a full table scan over an index scan. The default value of this parameter corresponds to the maximum I/O size that the database can perform efficiently. This value is platform-dependent and is 1 MB for most platforms. Because the parameter is expressed in blocks, it is set to a value equal to the maximum I/O size that can be performed efficiently divided by the standard block size. If the number of sessions is extremely large, then the multiblock read count value decreases to avoid the buffer cache getting flooded with too many table scan buffers. |
|
Controls adaptive plans. An adaptive plan has alternative choices. The optimizer decides on a plan at run time based on statistics collected as the query executes. By default, this parameter is
See "About Adaptive Query Plans". |
|
Controls the reporting mode for automatic reoptimization and adaptive plans (see "Adaptive Query Plans"). By default, reporting mode is off ( If set to |
|
Controls adaptive statistics. The optimizer can use adaptive statistics when query predicates are too complex to rely on base table statistics alone. By default,
See "Adaptive Statistics". |
|
Sets the optimizer mode at database instance startup. Possible values are |
|
Controls the cost analysis of an index probe with a nested loop. The range of values |
|
Adjusts the cost of index probes. The range of values is |
|
This parameter enables ( |
|
Enables or disables the use of invisible indexes. |
|
Controls whether the database uses the SQL query result cache for all queries, or only for the queries that are annotated with the result cache hint. When set to When setting this parameter, consider how the result cache handles PL/SQL functions. The database invalidates query results in the result cache using the same mechanism that tracks data dependencies for PL/SQL functions, but otherwise permits caching of queries that contain PL/SQL functions. Because PL/SQL function result cache invalidation does not track all kinds of dependencies (such as on sequences, |
|
Changes the memory allocated to the result cache. If you set this parameter to |
|
Specifies the maximum amount of cache memory that any single result can use. The default value is 5%, but you can specify any percentage value between |
|
Specifies the number of minutes for which a result that depends on remote database objects remains valid. The default is |
|
Enables the optimizer to cost a star transformation for star queries (if |
See Also:
-
Oracle Database Reference for complete information about the preceding initialization parameters
-
Oracle Database Performance Tuning Guide to learn how to tune the query result cache
- to learn more about star transformations
-
Oracle Database In-Memory Guide to learn more about Database In-Memory features
19.2.2 Enabling Optimizer Features
The OPTIMIZER_FEATURES_ENABLE
initialization parameter (or hint) controls a set of optimizer-related features, depending on the database release.
The parameter accepts one of a list of valid string values corresponding to the release numbers, such as 11.2.0.2
or 12.2.0.1
. You can use this parameter to preserve the old behavior of the optimizer after a database upgrade. For example, if you upgrade Oracle Database 12c Release 1 (12.1.0.2) to Oracle Database 12c Release 2 (12.2.0.1), then the default value of the OPTIMIZER_FEATURES_ENABLE
parameter changes from 12.1.0.2
to 12.2.0.1
.
For backward compatibility, you may not want the execution plans to change because of new optimizer features in a new release. In such cases, you can set OPTIMIZER_FEATURES_ENABLE
to an earlier version. If you upgrade to a new release, and if you want to enable the features in the new release, then you do not need to explicitly set the OPTIMIZER_FEATURES_ENABLE
initialization parameter.
Caution:
Oracle does not recommend explicitly setting the OPTIMIZER_FEATURES_ENABLE
initialization parameter to an earlier release. To avoid SQL performance regression that may result from execution plan changes, consider using SQL plan management instead.
Assumptions
This tutorial assumes the following:
-
You recently upgraded the database from Oracle Database 12c Release 1 (12 1.0.2) to Oracle Database 12c Release 2 (12.2.0.1).
-
You want to preserve the optimizer behavior from the earlier release.
To enable query optimizer features for a specific release:
-
Log in to the database with the appropriate privileges, and then query the current optimizer features settings.
For example, run the following SQL*Plus command:
SQL> SHOW PARAMETER optimizer_features_enable NAME TYPE VALUE ------------------------------------ ----------- -------- optimizer_features_enable string 12.2.0.1
-
Set the optimizer features setting at the instance or session level.
For example, run the following SQL statement to set the optimizer version to
12.1.0.2
:SQL> ALTER SYSTEM SET OPTIMIZER_FEATURES_ENABLE='12.1.0.2';
The preceding statement restores the optimizer functionality that existed in Oracle Database 12c Release 1 (12.1.0.2).
See Also:
-
Oracle Database Reference to learn about optimizer features enabled when you set
OPTIMIZER_FEATURES_ENABLE
to different release values
19.2.3 Choosing an Optimizer Goal
The optimizer goal is the prioritization of resource usage by the optimizer.
Using the OPTIMIZER_MODE
initialization parameter, you can set the following optimizer goals:
-
Best throughput (default)
When you set the
OPTIMIZER_MODE
value toALL_ROWS
, the database uses the least amount of resources necessary to process all rows that the statement accessed.For batch applications such as Oracle Reports, optimize for best throughput. Usually, throughput is more important in batch applications because the user is only concerned with the time necessary for the application to complete. Response time is less important because the user does not examine the results of individual statements while the application is running.
-
Best response time
When you set the
OPTIMIZER_MODE
value toFIRST_ROWS_
n
, the database optimizes with a goal of best response time to return the first n rows, where n equals1
,10
,100
, or1000
.For interactive applications in Oracle Forms or SQL*Plus, optimize for response time. Usually, response time is important because the interactive user is waiting to see the first row or rows that the statement accessed.
Assumptions
This tutorial assumes the following:
-
The primary application is interactive, so you want to set the optimizer goal for the database instance to minimize response time.
-
For the current session only, you want to run a report and optimize for throughput.
To enable query optimizer features for a specific release:
-
Connect SQL*Plus to the database with the appropriate privileges, and then query the current optimizer mode.
For example, run the following SQL*Plus command:
dba1@PROD> SHOW PARAMETER OPTIMIZER_MODE NAME TYPE VALUE ------------------------------------ ----------- -------- optimizer_mode string ALL_ROWS
-
At the instance level, optimize for response time.
For example, run the following SQL statement to configure the system to retrieve the first 10 rows as quickly as possible:
SQL> ALTER SYSTEM SET OPTIMIZER_MODE='FIRST_ROWS_10';
-
At the session level only, optimize for throughput before running a report.
For example, run the following SQL statement to configure only this session to optimize for throughput:
SQL> ALTER SESSION SET OPTIMIZER_MODE='ALL_ROWS';
See Also:
Oracle Database Reference to learn about the OPTIMIZER_MODE
initialization parameter
19.2.4 Controlling Adaptive Optimization
In Oracle Database, adaptive query optimization is the process by which the optimizer adapts an execution plan based on statistics collected at run time.
Adaptive plans are enabled when the following initialization parameters are set:
-
OPTIMIZER_ADAPTIVE_PLANS
isTRUE
(default) -
OPTIMIZER_FEATURES_ENABLE
is12.1.0.1
or later -
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
isFALSE
(default)
If OPTIMIZER_ADAPTIVE_REPORTING_ONLY
is set to true
, then adaptive optimization runs in reporting-only mode. In this case, the database gathers information required for adaptive optimization, but does not change the plans. An adaptive plan always chooses the default plan, but the database collects information about the execution as if the parameter were set to false
.
Adaptive statistics are enabled when the following initialization parameters are set:
-
OPTIMIZER_ADAPTIVE_STATISTICS
isTRUE
(the default isFALSE
) -
OPTIMIZER_FEATURES_ENABLE
is12.1.0.1
or later
Assumptions
This tutorial assumes the following:
-
The
OPTIMIZER_FEATURES_ENABLE
initialization parameter is set to12.1.0.1
or later. -
The
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
initialization parameter is set tofalse
(default). -
You want to disable adaptive plans for testing purposes so that the database generates only reports.
To disable adaptive plans:
-
Connect SQL*Plus to the database as
SYSTEM
, and then query the current settings.For example, run the following SQL*Plus command:
SHOW PARAMETER OPTIMIZER_ADAPTIVE_REPORTING_ONLY NAME TYPE VALUE ------------------------------------ ----------- ----- optimizer_adaptive_reporting_only boolean FALSE
-
At the session level, set the
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
initialization parameter totrue
.For example, in SQL*Plus run the following SQL statement:
ALTER SESSION SET OPTIMIZER_ADAPTIVE_REPORTING_ONLY=true;
-
Run a query.
-
Run
DBMS_XPLAN.DISPLAY_CURSOR
with the+REPORT
parameter.When the
+REPORT
parameter is set, the report shows the plan the optimizer would have picked if automatic reoptimization had been enabled.
See Also:
-
Oracle Database Reference to learn about the
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
initialization parameter -
Oracle Database PL/SQL Packages and Types Reference to learn about the
+REPORT
parameter of theDBMS_XPLAN.DISPLAY_CURSOR
function
19.3 Influencing the Optimizer with Hints
Optimizer hints are special comments in a SQL statement that pass instructions to the optimizer.
The optimizer uses hints to choose an execution plan for the statement unless prevented by some condition.
Note:
Oracle Database SQL Language Reference contains a complete reference for all SQL hints
This section contains the following topics:
- About Optimizer Hints
Use hints to influence the optimizer mode, query transformation, access path, join order, and join methods. - Guidelines for Join Order Hints
The join order can have a significant effect on the performance of a SQL statement. In some cases, you can specify join order hints in a SQL statement so that it does not access rows that have no effect on the result.
19.3.1 About Optimizer Hints
Use hints to influence the optimizer mode, query transformation, access path, join order, and join methods.
For example, The following figure shows how you can use a hint to tell the optimizer to use a specific index for a specific statement.
The advantage of hints is that they enable you to make decisions normally made by the optimizer. In a test environment, hints are useful for testing the performance of a specific access path. For example, you may know that an index is more selective for certain queries, as in Figure 19-2. In this case, the hint may cause the optimizer to generate a better plan.
The disadvantage of hints is the extra code that you must manage, check, and control. Hints were introduced in Oracle7, when users had little recourse if the optimizer generated suboptimal plans. Because changes in the database and host environment can make hints obsolete or have negative consequences, a good practice is to test using hints, but use other techniques to manage execution plans.
Oracle provides several tools, including SQL Tuning Advisor, SQL plan management, and SQL Performance Analyzer, to address performance problems not solved by the optimizer. Oracle strongly recommends that you use these tools instead of hints because they provide fresh solutions as the data and database environment change.
This section contains the following topics:
- Types of Hints
You can use hints for tables, query blocks, and statements. - Scope of Hints
When you specify a hint, it optimizes only the statement block in which it appears, overriding any instance-level or session-level parameters. - Guidelines for Hints
You must enclose hints within a SQL comment.
See Also:
Oracle Database SQL Language Reference for the most common hints by functional category.
19.3.1.1 Types of Hints
You can use hints for tables, query blocks, and statements.
Hints fall into the following types:
-
Single-table
Single-table hints are specified on one table or view.
INDEX
andUSE_NL
are examples of single-table hints. The following statement uses a single-table hint:SELECT /*+ INDEX (employees emp_department_ix)*/ employee_id, department_id FROM employees WHERE department_id > 50;
-
Multi-table
Multi-table hints are like single-table hints except that the hint can specify multiple tables or views.
LEADING
is an example of a multi-table hint. The following statement uses a multi-table hint:SELECT /*+ LEADING(e j) */ * FROM employees e, departments d, job_history j WHERE e.department_id = d.department_id AND e.hire_date = j.start_date;
Note:
USE_NL(table1 table2)
is not considered a multi-table hint because it is a shortcut forUSE_NL(table1)
andUSE_NL(table2)
. -
Query block
Query block hints operate on single query blocks.
STAR_TRANSFORMATION
andUNNEST
are examples of query block hints. The following statement uses a query block hint:SELECT /*+ STAR_TRANSFORMATION */ s.time_id, s.prod_id, s.channel_id FROM sales s, times t, products p, channels c WHERE s.time_id = t.time_id AND s.prod_id = p.prod_id AND s.channel_id = c.channel_id AND c.channel_desc = 'Tele Sales';
-
Statement
Statement hints apply to the entire SQL statement.
ALL_ROWS
is an example of a statement hint. The following statement uses a statement hint:SELECT /*+ ALL_ROWS */ * FROM sales;
19.3.1.2 Scope of Hints
When you specify a hint, it optimizes only the statement block in which it appears, overriding any instance-level or session-level parameters.
A statement block is one of the following:
-
A simple
MERGE
,SELECT
,INSERT
,UPDATE
, orDELETE
statement -
A parent statement or a subquery of a complex statement
-
A part of a query using set operators (
UNION
,MINUS
,INTERSECT
)
Example 19-1 Query Using a Set Operator
The following query consists of two component queries and the UNION
operator:
SELECT /*+ FIRST_ROWS(10) */ prod_id, time_id FROM 2010_sales
UNION ALL
SELECT /*+ ALL_ROWS */ prod_id, time_id FROM current_year_sales;
The preceding statement has two blocks, one for each component query. Hints in the first component query apply only to its optimization, not to the optimization of the second component query. For example, in the first week of 2015 you query current year and last year sales. You apply FIRST_ROWS(10)
to the query of last year's (2014) sales and the ALL_ROWS
hint to the query of this year's (2015) sales.
See Also:
Oracle Database SQL Language Reference for an overview of hints
19.3.1.3 Guidelines for Hints
You must enclose hints within a SQL comment.
The hint comment must immediately follow the first keyword of a SQL statement block. You can use either style of comment: a slash-star (/*
) or pair of dashes (--
). The plus-sign (+) hint delimiter must come immediately after the comment delimiter, as in the following fragment:
SELECT /*+ hint_text */ ...
The database ignores incorrectly specified hints. The database also ignores combinations of conflicting hints, even if these hints are correctly specified. If one hint is incorrectly specified, but a hint in the same comment is correctly specified, then the database considers the correct hint.
Caution:
The database does not issue error messages for hints that it ignores.
A statement block can have only one comment containing hints, but it can contain many space-separated hints. For example, a complex query may include multiple table joins. If you specify only the INDEX
hint for a specified table, then the optimizer must determine the remaining access paths and corresponding join methods. The optimizer may not use the INDEX
hint because the join methods and access paths prevent it. Example 19-2 uses multiple hints to specify the exact join order.
Example 19-2 Multiple Hints
SELECT /*+ LEADING(e2 e1) USE_NL(e1) INDEX(e1 emp_emp_id_pk)
USE_MERGE(j) FULL(j) */
e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal
FROM employees e1, employees e2, job_history j
WHERE e1.employee_id = e2.manager_id
AND e1.employee_id = j.employee_id
AND e1.hire_date = j.start_date
GROUP BY e1.first_name, e1.last_name, j.job_id
ORDER BY total_sal;
See Also:
Oracle Database SQL Language Reference to learn about the syntax rules for comments and hints
19.3.2 Guidelines for Join Order Hints
The join order can have a significant effect on the performance of a SQL statement. In some cases, you can specify join order hints in a SQL statement so that it does not access rows that have no effect on the result.
The driving table in a join is the table to which other tables are joined. In general, the driving table contains the filter condition that eliminates the highest percentage of rows in the table.
Consider the following guidelines:
-
Avoid a full table scan when an index retrieves the requested rows more efficiently.
-
Avoid using an index that fetches many rows from the driving table when you can use a different index that fetches a small number of rows.
-
Choose the join order so that you join fewer rows to tables later in the join order.
The following example shows how to tune join order effectively:
SELECT *
FROM taba a,
tabb b,
tabc c
WHERE a.acol BETWEEN 100 AND 200
AND b.bcol BETWEEN 10000 AND 20000
AND c.ccol BETWEEN 10000 AND 20000
AND a.key1 = b.key1
AND a.key2 = c.key2;
-
Choose the driving table and the driving index (if any).
Each of the first three conditions in the previous example is a filter condition that applies to a single table. The last two conditions are join conditions.
Filter conditions dominate the choice of driving table and index. In general, the driving table contains the filter condition that eliminates the highest percentage of rows. Thus, because the range of 100 to 200 is narrow compared with the range of
acol
, but the ranges of 10000 and 20000 are relatively large,taba
is the driving table, all else being equal.With nested loops joins, the joins occur through the join indexes, which are the indexes on the primary or foreign keys used to connect that table to an earlier table in the join tree. Rarely do you use the indexes on the non-join conditions, except for the driving table. Thus, after
taba
is chosen as the driving table, use the indexes onb.key1
andc.key2
to drive intotabb
andtabc
, respectively. -
Choose the best join order, driving to the best unused filters earliest.
You can reduce the work of the following join by first joining to the table with the best still-unused filter. Thus, if
bcol BETWEEN
is more restrictive (rejects a higher percentage of the rows) thanccol BETWEEN
, then the last join becomes easier (with fewer rows) iftabb
is joined beforetabc
. -
You can use the
ORDERED
orSTAR
hint to force the join order.
See Also:
Oracle Database Reference to learn about OPTIMIZER_MODE