This chapter explains what optimizer statistics collection is and how to set statistics preferences.
In Oracle Database, optimizer statistics collection is the gathering of optimizer statistics for database objects, including fixed objects. The database can collect optimizer statistics automatically. You can also collect them manually using the DBMS_STATS
package.
See Also:
The contents of tables and associated indexes change frequently, which can lead the optimizer to choose suboptimal execution plan for queries. To avoid potential performance issues, statistics must be kept current.
To minimize DBA involvement, Oracle Database automatically gathers optimizer statistics at various times. Some automatic options are configurable, such enabling AutoTask to run DBMS_STATS
.
You can manage optimizer statistics either through Oracle Enterprise Manager Cloud Control (Cloud Control) or using PL/SQL on the command line.
The Manage Optimizer Statistics page in Cloud Control is a GUI that enables you to manage optimizer statistics.
Oracle Enterprise Manager Cloud Control enables you to manage multiple databases within a single GUI-based framework.
To access a database home page using Cloud Control:
Log in to Cloud Control with the appropriate credentials.
Under the Targets menu, select Databases.
In the list of database targets, select the target for the Oracle Database instance that you want to administer.
If prompted for database credentials, then enter the minimum credentials necessary for the tasks you intend to perform.
See Also:
Cloud Control online help
You can perform most necessary tasks relating to optimizer statistics through pages linked to by the Optimizer Statistics Console page.
To manage optimizer statistics using Cloud Control:
Access the Database Home page.
From the Performance menu, select SQL, then Optimizer Statistics.
The Optimizer Statistics Console appears.
See Also:
Online Help for Oracle Enterprise Manager Cloud Control
The DBMS_STATS
package performs most optimizer statistics tasks. To enable and disable automatic statistics gathering, use the DBMS_AUTO_TASK_ADMIN
PL/SQL package.
See Also:
Oracle Database PL/SQL Packages and Types Reference to learn how to use DBMS_STATS
and DBMS_AUTO_TASK_ADMIN
This topic explains how to set optimizer statistics defaults using DBMS_STATS.SET_*_PREFS
procedures.
This section contains the following topics:
The optimizer statistics preferences set the default values of the parameters used by automatic statistics collection and the DBMS_STATS
statistics gathering procedures.
You can set optimizer statistics preferences at the table, schema, database (all tables), and global (tables with no preferences and any tables created in the future) levels. The procedure names follow the form SET_*_PREFS
.
Preferences enable you to maintain optimizer statistics automatically when some objects require settings that differ from the default. In this way, you have more control over how Oracle Database gathers statistics.
Preferences that you can set include, but are not limited to, the following:
ESTIMATE_PERCENT
This preference determines the percentage of rows to estimate.
CONCURRENT
This preference determines whether the database gathers statistics concurrently on multiple objects, or serially, one object at a time.
STALE_PERCENT
This preference determines the percentage of rows in a table that must change before the database deems the statistics stale and in need of regathering.
AUTO_STAT_EXTENSIONS
When set to the non-default value of ON
, this preference enables a SQL plan directive to trigger the creation of column group statistics based on usage of columns in the predicates in the workload.
INCREMENTAL
This preference determines whether the database maintains the global statistics of a partitioned table without performing a full table scan. Possible values are TRUE
and FALSE
.
For example, by the default setting for INCREMENTAL
is FALSE
. You can set INCREMENTAL
to TRUE
for a range-partitioned table when the last few partitions are updated. Also, when performing a partition exchange operation on a nonpartitioned table, Oracle recommends that you set INCREMENTAL
to TRUE
and INCREMENTAL_LEVEL
to TABLE
. With these settings, DBMS_STATS
gathers table-level synopses on this table.
INCREMENTAL_LEVEL
This preference controls what synopses to collect when INCREMENTAL
preference is set to TRUE
. It takes two values: TABLE
or PARTITION
.
APPROXIMATE_NDV_ALGORITHM
This preference controls which algorithm to use when calculating the number of distinct values for partitioned tables using incremental statistics.
The DBMS_STATS.SET_*_PREFS
procedures change the defaults of parameters used by the DBMS_STATS.GATHER_*_STATS
procedures. To query the current preferences, use the DBMS_STATS.GET_PREFS
function.
When setting statistics preferences, the order of precedence is:
Table preference (set for a specific table, all tables in a schema, or all tables in the database)
Global preference
Default preference
The following table summarizes the relevant DBMS_STATS
procedures.
Table 12-1 DBMS_STATS Procedures for Setting Optimizer Statistics Preferences
Procedure | Scope |
---|---|
|
Specified table only. |
|
All existing tables in the specified schema. This procedure calls |
|
All user-defined schemas in the database. You can include system-owned schemas such as This procedure calls |
|
Any table that does not have an existing table preference. All parameters default to the global setting unless a table preference is set or the parameter is explicitly set in the With You can only set the |
See Also:
Oracle Database PL/SQL Packages and Types Reference to learn about the DBMS_STATS
procedures for setting optimizer statistics
The preference_overrides_parameter
statistics preference determines whether, when gathering optimizer statistics, to override the input value of a parameter with the statistics preference. In this way, you control when the database honors a parameter value passed to the statistics gathering procedures.
When preference_overrides_parameter
is set to FALSE
(default), the input values for statistics gathering procedures are honored. When set to TRUE
, the input values are ignored.
Set the preference_overrides_parameter
preference using the SET_TABLE_PREFS
, SET_SCHEMA_PREFS
, or SET_GLOBAL_PREFS
procedures in DBMS_STATS
. Regardless of whether preference_overrides_parameter
is set, the database uses the same order of precedence for setting statistics:
Table preference (set for a specific table, all tables in a schema, or all tables in the database)
Global preference
Default preference
Example 12-1 Overriding Statistics Preferences at the Table Level
In this example, legacy scripts set estimate_percent
explicitly rather than using the recommended AUTO_SAMPLE_SIZE
. Your goal is to prevent users from using these scripts to set preferences on the sh.costs
table.
Table 12-2 Overriding Statistics Preferences at the Table Level
Action | Description |
---|---|
SQL> SELECT DBMS_STATS.GET_PREFS ('estimate_percent', 'sh','costs') AS "STAT_PREFS" FROM DUAL; STAT_PREFS ---------- DBMS_STATS.AUTO_SAMPLE_SIZE |
No preference for |
SQL> EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'costs', 'preference_overrides_parameter', 'true'); PL/SQL procedure successfully completed. |
By default, Oracle Database accepts preferences that are passed to the |
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS ('sh', 'costs', estimate_percent=>100); PL/SQL procedure successfully completed. |
You attempt to set |
Example 12-2 Overriding Statistics Preferences at the Global Level
In this example, you set estimate_percent
to 5
at the global level, which mean this preference applies to every table in the database that does not have a table preference set. You then set an override on the sh.sales
table, which does not have a table-level preference set, to prevent users from overriding the global setting in their scripts.
Table 12-3 Overriding Statistics Preferences at the Global Level
Action | Description |
---|---|
SQL> EXEC DBMS_STATS.SET_GLOBAL_PREFS ('estimate_percent', '5'); PL/SQL procedure successfully completed. |
You use the |
SQL> EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'sales', 'preference_overrides_parameter', 'true'); PL/SQL procedure successfully completed. |
You use |
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS ('sh', 'costs', estimate_percent=>10); PL/SQL procedure successfully completed. |
You attempt to set |
See Also:
Oracle Database PL/SQL Packages and Types Reference to learn about the DBMS_STATS
procedures for setting optimizer statistics
This example illustrates the relationship between SET_TABLE_PREFS
, SET_SCHEMA_STATS
, and SET_DATABASE_PREFS
.
Table 12-4 Changing Preferences for Statistics Gathering Procedures
Action | Description |
---|---|
SQL> SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh','costs') AS "STAT_PREFS" FROM DUAL; STAT_PREFS ---------- TRUE |
You query the |
SQL> EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'costs', 'incremental', 'false'); PL/SQL procedure successfully completed. |
You use |
SQL> SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL; STAT_PREFS ---------- FALSE |
You query the |
SQL> EXEC DBMS_STATS.SET_SCHEMA_PREFS ('sh', 'incremental', 'true'); PL/SQL procedure successfully completed. |
You use |
SQL> SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL; STAT_PREFS ---------- TRUE |
You query the |
SQL> EXEC DBMS_STATS.SET_DATABASE_PREFS ('incremental', 'false'); PL/SQL procedure successfully completed. |
You use |
SQL> SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL; STAT_PREFS ---------- FALSE |
You query the |
A global preference applies to any object in the database that does not have an existing table preference. You can set optimizer statistics preferences at the global level using Cloud Control.
To set global optimizer statistics preferences using Cloud Control:
Go to the Optimizer Statistics Console page, as explained in "Accessing the Optimizer Statistics Console".
Click Global Statistics Gathering Options.
The Global Statistics Gathering Options page appears.
Make your desired changes, and click Apply.
See Also:
Online Help for Oracle Enterprise Manager Cloud Control
You can set optimizer statistics preferences at the database, schema, and table level using Cloud Control.
To set object-level optimizer statistics preferences using Cloud Control:
Go to the Optimizer Statistics Console, as explained in "Accessing the Optimizer Statistics Console".
Click Object Level Statistics Gathering Preferences.
The Object Level Statistics Gathering Preferences page appears.
To modify table preferences for a table that has preferences set at the table level, do the following (otherwise, skip to the next step):
Enter values in Schema and Table Name. Leave Table Name blank to see all tables in the schema.
The page refreshes with the table names.
Select the desired tables and click Edit Preferences.
The General subpage of the Edit Preferences page appears.
Change preferences as needed and click Apply.
To set preferences for a table that does not have preferences set at the table level, do the following (otherwise, skip to the next step):
Click Add Table Preferences.
The General subpage of the Add Table Preferences page appears.
In Table Name, enter the schema and table name.
Change preferences as needed and click OK.
To set preferences for a schema, do the following:
Click Set Schema Tables Preferences.
The General subpage of the Edit Schema Preferences page appears.
In Schema, enter the schema name.
Change preferences as needed and click OK.
See Also:
Online Help for Oracle Enterprise Manager Cloud Control
If you do not use Cloud Control to set optimizer statistics preferences, then you can invoke the DBMS_STATS
procedures described in Table 12-1.
Prerequisites
This task has the following prerequisites:
To set the global or database preferences, you must have SYSDBA
privileges, or both ANALYZE ANY DICTIONARY
and ANALYZE ANY
system privileges.
To set schema preferences, you must connect as owner, or have SYSDBA
privileges, or have the ANALYZE ANY
system privilege.
To set table preferences, you must connect as owner of the table or have the ANALYZE ANY
system privilege.
To set optimizer statistics preferences from the command line:
Connect SQL*Plus to the database with the necessary privileges.
Optionally, call the DBMS_STATS.GET_PREFS
procedure to see preferences set at the object level, or at the global level if a specific table is not set.
For example, obtain the STALE_PERCENT
parameter setting for the sh.sales
table as follows:
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', 'SH', 'SALES') FROM DUAL;
Execute the appropriate procedure from Table 12-1, specifying the following parameters:
ownname
- Set schema name (SET_TAB_PREFS
and SET_SCHEMA_PREFS
only)
tabname
- Set table name (SET_TAB_PREFS
only)
pname
- Set parameter name
pvalue
- Set parameter value
add_sys
- Include system tables (optional, SET_DATABASE_PREFS
only)
The following example specifies that 13% of rows in sh.sales
must change before the statistics on that table are considered stale:
EXEC DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'STALE_PERCENT', '13');
Optionally, query the *_TAB_STAT_PREFS
view to confirm the change.
For example, query DBA_TAB_STAT_PREFS
as follows:
COL OWNER FORMAT a5 COL TABLE_NAME FORMAT a15 COL PREFERENCE_NAME FORMAT a20 COL PREFERENCE_VALUE FORMAT a30 SELECT * FROM DBA_TAB_STAT_PREFS;
Sample output appears as follows:
OWNER TABLE_NAME PREFERENCE_NAME PREFERENCE_VALUE ----- --------------- -------------------- ------------------------------ OE CUSTOMERS NO_INVALIDATE DBMS_STATS.AUTO_INVALIDATE SH SALES STALE_PERCENT 13
See Also:
Oracle Database PL/SQL Packages and Types Reference for descriptions of the parameter names and values for program units
Dynamic statistics are an optimization technique in which the database executes a recursive SQL statement to scan a small random sample of a table's blocks to estimate predicate selectivities. In this way, the database determines better default statistics for unanalyzed segments, and verifies its estimates.
By default, when optimizer statistics are missing, stale, or insufficient, dynamic statistics automatically run recursive SQL during parsing to scan a small random sample of table blocks.
This section contains the following topics:
See Also:
The dynamic statistics level controls both when the database gathers dynamic statistics, and the size of the sample that the optimizer uses to gather the statistics.
Set the dynamic statistics level using either the OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter or a statement hint.
Note:
Dynamic statistics were called dynamic sampling in releases earlier than Oracle Database 12c Release 1 (12.1).
The following table describes the levels for dynamic statistics. Note the following:
If OPTIMIZER_DYNAMIC_STATISTICS
is true
, and if dynamic statistics are not disabled, then the database may choose to use dynamic statistics when a SQL statement uses parallel execution.
If OPTIMIZER_ADAPTIVE_STATISTICS
is true
, then the optimizer uses dynamic statistics when relevant SQL plan directives exist. The database maintains the resulting statistics in the SQL plan directives store, making them available to other queries.
Table 12-5 Dynamic Statistics Levels
Level | When the Optimizer Uses Dynamic Statistics | Sample Size (Blocks) |
---|---|---|
0 |
Do not use dynamic statistics. |
n/a |
1 |
Use dynamic statistics for all tables that do not have statistics, but only if the following criteria are met:
|
32 |
2 |
Use dynamic statistics if at least one table in the statement has no statistics. This is the default value. |
64 |
3 |
Use dynamic statistics if any of the following conditions is true:
|
64 |
4 |
Use dynamic statistics if any of the following conditions is true:
|
64 |
5 |
The criteria are identical to level 4, but the database uses a different sample size. |
128 |
6 |
The criteria are identical to level 4, but the database uses a different sample size. |
256 |
7 |
The criteria are identical to level 4, but the database uses a different sample size. |
512 |
8 |
The criteria are identical to level 4, but the database uses a different sample size. |
1024 |
9 |
The criteria are identical to level 4, but the database uses a different sample size. |
4086 |
10 |
The criteria are identical to level 4, but the database uses a different sample size. |
All blocks |
11 |
The database uses adaptive dynamic sampling automatically when the optimizer deems it necessary. |
Automatically determined |
See Also:
Oracle Database Reference to learn about the OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter
Determining a database-level setting that would be beneficial to all SQL statements can be difficult. When setting the level for dynamic statistics, Oracle recommends setting the OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter at the session level.
Assumptions
This tutorial assumes the following:
You want correct selectivity estimates for the following query, which has WHERE
clause predicates on two correlated columns:
SELECT * FROM sh.customers WHERE cust_city='Los Angeles' AND cust_state_province='CA';
The preceding query uses serial processing.
The sh.customers
table contains 932 rows that meet the conditions in the query.
You have gathered statistics on the sh.customers
table.
You created an index on the cust_city
and cust_state_province
columns.
The OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter is set to the default level of 2
.
To set the dynamic statistics level manually:
Connect SQL*Plus to the database with the appropriate privileges, and then explain the execution plan as follows:
EXPLAIN PLAN FOR SELECT * FROM sh.customers WHERE cust_city='Los Angeles' AND cust_state_province='CA';
Query the plan as follows:
SET LINESIZE 130 SET PAGESIZE 0 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
The output appears below (the example has been reformatted to fit on the page):
------------------------------------------------------------------------------- |Id| Operation | Name |Rows|Bytes|Cost | Time | ------------------------------------------------------------------------------- | 0| SELECT STATEMENT | | 53| 9593|53(0)|00:00:01| | 1| TABLE ACCESS BY INDEX ROWID|CUSTOMERS | 53| 9593|53(0)|00:00:01| |*2| INDEX RANGE SCAN |CUST_CITY_STATE_IND| 53| 9593| 3(0)|00:00:01| ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("CUST_CITY"='Los Angeles' AND "CUST_STATE_PROVINCE"='CA')
The columns in the WHERE
clause have a real-world correlation, but the optimizer is not aware that Los Angeles is in California and assumes both predicates reduce the number of rows returned. Thus, the table contains 932 rows that meet the conditions, but the optimizer estimates 53, as shown in bold.
If the database had used dynamic statistics for this plan, then the Note
section of the plan output would have indicated this fact. The optimizer did not use dynamic statistics because the statement executed serially, standard statistics exist, and the parameter OPTIMIZER_DYNAMIC_SAMPLING
is set to the default of 2
.
Set the dynamic statistics level to 4
in the session using the following statement:
ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=4;
Explain the plan again:
EXPLAIN PLAN FOR SELECT * FROM sh.customers WHERE cust_city='Los Angeles' AND cust_state_province='CA';
The new plan shows a more accurate estimate of the number of rows, as shown by the value 932 in bold:
PLAN_TABLE_OUTPUT --------------------------------------------------------------------------- Plan hash value: 2008213504 --------------------------------------------------------------------------- | Id | Operation | Name |Rows | Bytes |Cost (%CPU)|Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 932 | 271K| 406 (1)| 00:00:05 | |* 1 | TABLE ACCESS FULL| CUSTOMERS | 932 | 271K| 406 (1)| 00:00:05 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("CUST_CITY"='Los Angeles' AND "CUST_STATE_PROVINCE"='CA') Note ----- - dynamic statistics used for this statement (level=4)
The note at the bottom of the plan indicates that the sampling level is 4
. The additional dynamic statistics made the optimizer aware of the real-world relationship between the cust_city
and cust_state_province
columns, thereby enabling it to produce a more accurate estimate for the number of rows: 932 rather than 53.
See Also:
Oracle Database SQL Language Reference to learn about setting sampling levels with the DYNAMIC_SAMPLING
hint
Oracle Database Reference to learn about the OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter
In general, the best practice is not to incur the cost of dynamic statistics for queries whose compile times must be as fast as possible, for example, unrepeated OLTP queries.
To disable dynamic statistics at the session level:
Connect SQL*Plus to the database with the appropriate privileges.
Set the dynamic statistics level to 0
.
For example, run the following statement:
ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=0;
See Also:
Oracle Database Reference to learn about the OPTIMIZER_DYNAMIC_SAMPLING
initialization parameter
A SQL plan directive is additional information and instructions that the optimizer can use to generate a more optimal plan.
A directive informs the database that the optimizer is misestimate cardinalities of certain types of predicates, and alerts DBMS_STATS
to gather additional statistics in the future. Thus, directives have an effect on statistics gathering.
The database automatically creates and manages SQL plan directives in the SGA, and then periodically writes them to the data dictionary. If the directives are not used within 53 weeks, then the database automatically purges them.
You can use DBMS_SPD
procedures and functions to alter, save, drop, and transport directives manually. The following table lists some of the more commonly used procedures and functions.
Table 12-6 DBMS_SPD Procedures
Procedure | Description |
---|---|
|
Forces the database to write directives from memory to persistent storage in the |
|
Drops a SQL plan directive. If a directive that triggers dynamic sampling is creating unacceptable performance overhead, then you may want to remove it manually. If a SQL plan directive is dropped manually or automatically, then the database can re-create it. To prevent its re-creation, you can use
To disable SQL plan directives, set |
Prerequisites
You must have the Administer SQL Management Object privilege to execute the DBMS_SPD
APIs.
Assumptions
This tutorial assumes that you want to do the following:
Write all directives for the sh
schema to persistent storage.
Delete all directives for the sh
schema.
To write and then delete all sh schema plan directives:
Start SQL*Plus and connect to the database with administrator privileges.
Force the database to write the SQL plan directives to disk.
For example, execute the following DBMS_SPD
program:
BEGIN DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE; END; /
Query the data dictionary for information about existing directives in the sh
schema.
Example 12-3 queries the data dictionary for information about the directive.
Delete the existing SQL plan directive for the sh
schema.
The following PL/SQL program unit deletes the SQL plan directive with the ID 1484026771529551585
:
BEGIN DBMS_SPD.DROP_SQL_PLAN_DIRECTIVE ( directive_id => 1484026771529551585 ); END; /
See Also:
Oracle Database Reference to learn about DBA_SQL_PLAN_DIRECTIVES
Oracle Database PL/SQL Packages and Types Reference to learn about the DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE
procedure
Example 12-3 Display Directives for sh Schema
This example shows SQL plan directives, and the results of SQL plan directive dynamic sampling queries.
SELECT TO_CHAR(d.DIRECTIVE_ID) dir_id, o.OWNER, o.OBJECT_NAME, o.SUBOBJECT_NAME col_name, o.OBJECT_TYPE object, d.TYPE, d.STATE, d.REASON FROM DBA_SQL_PLAN_DIRECTIVES d, DBA_SQL_PLAN_DIR_OBJECTS o WHERE d.DIRECTIVE_ID=o.DIRECTIVE_ID AND o.OWNER IN ('SH') ORDER BY 1,2,3,4,5; DIR_ID OWN OBJECT_NA COL_NAME OBJECT TYPE STATE REASON ------------------- --- --------- ---------- ------- -------- ---------- ------------ 1484026771529551585 SH CUSTOMERS COUNTRY_ID COLUMN DYNAMIC_ SUPERSEDED SINGLE TABLE SAMPLING CARDINALITY MISESTIMATE 1484026771529551585 SH CUSTOMERS CUST_STATE_ COLUMN DYNAMIC_ SUPERSEDED SINGLE TABLE PROVINCE SAMPLING CARDINALITY MISESTIMATE 1484026771529551585 SH CUSTOMERS TABLE DYNAMIC_ SUPERSEDED SINGLE TABLE SAMPLING CARDINALITY MISESTIMATE 9781501826140511330 SH dyg4msnst5 SQL STA DYNAMIC_ USABLE VERIFY TEMENT SAMPLING CARDINALITY _RESULT ESTIMATE 9872337207064898539 SH TIMES TABLE DYNAMIC_ USABLE VERIFY SAMPLING CARDINALITY _RESULT ESTIMATE 9781501826140511330 SH 2nk1v0fdx0 SQL STA DYNAMIC_ USABLE VERIFY TEMENT SAMPLING CARDINALITY _RESULT ESTIMATE
See Also:
Oracle Database PL/SQL Packages and Types Reference for complete syntax and semantics for the DBMS_SPD
package.