SQL调优指南笔记12:Configuring Options for Optimizer Statistics Gathering

Posted dingdingfish

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL调优指南笔记12:Configuring Options for Optimizer Statistics Gathering相关的知识,希望对你有一定的参考价值。

本文为SQL Tuning Guide第12章“Configuring Options for Optimizer Statistics Gathering”的笔记。

重要基本概念

本章解释什么是优化器统计信息收集以及如何设置统计信息首选项。

12.1 About Optimizer Statistics Collection

在 Oracle 数据库中,优化器统计信息收集是收集数据库对象(包括固定对象)的优化器统计信息。

数据库可以自动收集优化器统计信息。 您还可以使用 DBMS_STATS 包手动收集它们。

12.1.1 Purpose of Optimizer Statistics Collection

表和关联索引的内容经常变化,这会导致优化器为查询选择次优的执行计划。 为避免潜在的性能问题,统计信息必须保持最新。

为了最大限度地减少 DBA 的参与,Oracle 数据库会在不同时间自动收集优化器统计信息。 一些自动选项是可配置的,例如启用 AutoTask 来运行 DBMS_STATS。

12.1.2 User Interfaces for Optimizer Statistics Management

您可以通过 Oracle Enterprise Manager Cloud Control (Cloud Control) 或在命令行上使用 PL/SQL 来管理优化器统计信息。

12.1.2.1 Graphical Interface for Optimizer Statistics Management

The Manage Optimizer Statistics page in Cloud Control is a GUI that enables you to manage optimizer statistics.

12.1.2.1 Graphical Interface for Optimizer Statistics Management

Oracle Enterprise Manager Cloud Control 使您能够在一个基于 GUI 的框架内管理多个数据库。

使用 Cloud Control 访问数据库主页:

  1. 使用适当的凭据登录到 Cloud Control。
  2. 在Targets菜单下,选择Databases。
  3. 在数据库目标列表中,选择您要管理的 Oracle 数据库实例的目标。
  4. 如果提示输入数据库凭据,请输入您要执行的任务所需的最低凭据。
12.1.2.2 Command-Line Interface for Optimizer Statistics Management

您可以通过Optimizer Statistics Console页面链接的页面执行与优化器统计信息相关的最必要的任务。
使用 Cloud Control 管理优化器统计信息:

  1. 在 Cloud Control 中,访问数据库主页。
  2. 从 Performance 菜单中选择 SQL,然后选择 Optimizer Statistics。
  3. 出现优化器统计控制台。

12.1.2.2 Command-Line Interface for Optimizer Statistics Management

DBMS_STATS 包执行大多数优化器统计任务。

要启用和禁用自动统计信息收集,请使用 DBMS_AUTO_TASK_ADMIN PL/SQL 包。

12.2 Setting Optimizer Statistics Preferences

本主题说明如何使用 DBMS_STATS.SET_*_PREFS 过程设置优化器统计默认值。

12.2.1 About Optimizer Statistics Preferences

优化器统计首选项设置自动统计收集和 DBMS_STATS 统计收集过程使用的参数的默认值。

12.2.1.1 Purpose of Optimizer Statistics Preferences

当某些对象需要与默认设置不同的设置时,首选项使您能够自动维护优化器统计信息。

首选项让您可以更精细地控制 Oracle 数据库如何收集统计信息。 您可以在以下级别设置优化器统计首选项:

  • 模式
  • 数据库(所有表)
  • 全局(没有首选项的表和将来创建的任何表)

用于设置首选项的 DBMS_STATS 过程具有 SET_*_PREFS 形式的名称。

12.2.1.2 Examples of Statistics Preferences

使用 SET_*_PREFS 过程的 pname 参数设置首选项。

您可以设置的首选项包括但不限于以下内容:

  • ESTIMATE_PERCENT
    此首选项确定要估算的行的百分比。
  • CONCURRENT
    此首选项确定数据库是同时收集多个对象的统计信息,还是一次连续收集一个对象的统计信息。
  • STALE_PERCENT
    此首选项确定在数据库认为统计信息过时并需要重新收集之前必须更改的表中行的百分比。
  • AUTO_STAT_EXTENSIONS
    当设置为非默认值 ON 时,此首选项允许 SQL 计划指令根据工作负载中谓词中列的使用情况触发列组统计信息的创建。
  • INCREMENTAL
    此首选项确定数据库是否在不执行全表扫描的情况下维护分区表的全局统计信息。可能的值为 TRUE 和 FALSE。
    例如,INCREMENTAL 的默认设置是 FALSE。当更新最后几个分区时,您可以将范围分区表的 INCREMENTAL 设置为 TRUE。此外,在对非分区表执行分区交换操作时,Oracle 建议您将 INCREMENTAL 设置为 TRUE,将 INCREMENTAL_LEVEL 设置为 TABLE。使用这些设置,DBMS_STATS 会在该表上收集表级概要。
  • INCREMENTAL_LEVEL
    当 INCREMENTAL 首选项设置为 TRUE 时,此首选项控制要收集的概要。它有两个值:TABLE 或 PARTITION。
  • APPROXIMATE_NDV_ALGORITHM
    此首选项控制在使用增量统计计算分区表的不同值的数量时使用哪种算法。
  • ROOT_TRIGGER_PDB
    此首选项控制是接受还是拒绝从 CDB 中的应用程序根触发的统计信息收集。
    默认情况下,在为应用程序根中的元数据链接表收集统计信息时,如果应用程序 PDB 的统计信息过时,则数据库不会触发对应用程序 PDB 的统计信息收集。当设置为 TRUE 时,ROOT_TRIGGER_PDB 触发对应用程序 PDB 的统计信息收集,然后在应用程序根中派生全局统计信息。

12.2.1.3 DBMS_STATS Procedures for Setting Statistics Preferences

DBMS_STATS.SET_PREFS 过程更改 DBMS_STATS.GATHER_STATS 过程使用的参数的默认值。 要查询当前首选项,请使用 DBMS_STATS.GET_PREFS 函数。

设置统计首选项时,优先顺序(由低到高)为:

  1. 表首选项(为特定表、架构中的所有表或数据库中的所有表设置)
  2. 全局首选项
  3. 默认首选项

下表总结了相关的 DBMS_STATS 过程。

过程范围
SET_TABLE_PREFS仅指定表。
SET_SCHEMA_PREFS指定模式中的所有现有表。此过程为指定模式中的每个表调用 SET_TABLE_PREFS。 调用 SET_SCHEMA_PREFS 不会影响运行后创建的任何新表。 新表对所有参数使用 GLOBAL_PREF 值。
SET_DATABASE_PREFS数据库中所有用户定义的模式。 您可以通过将 ADD_SYS 参数设置为 true 来包含系统拥有的模式,例如 SYS 和 SYSTEM。此过程为指定模式中的每个表调用 SET_TABLE_PREFS。 调用 SET_DATABASE_PREFS 不会影响运行后创建的任何新对象。 新对象对所有参数使用 GLOBAL_PREF 值。
SET_GLOBAL_PREFS没有现有表首选项的任何表。
除非设置了表首选项或在 DBMS_STATS.GATHER_*_STATS 语句中显式设置了参数,否则所有参数都默认为全局设置。 SET_GLOBAL_PREFS 所做的更改会影响它运行后创建的任何新对象。 新对象对所有参数使用 SET_GLOBAL_PREFS 值。
使用 SET_GLOBAL_PREFS,您可以为参数 AUTOSTATS_TARGET 设置默认值。 此附加参数控制在夜间维护窗口中运行的自动统计收集作业会影响哪些对象。 AUTOSTATS_TARGET 的可能值为 ALL、ORACLE 和 AUTO(默认值)。
您只能在全局级别设置 CONCURRENT 首选项。 您不能使用 SET_GLOBAL_PREFS 设置首选项 INCREMENTAL_LEVEL。

12.2.1.4 Statistics Preference Overrides

preference_overrides_parameter 统计首选项确定在收集优化器统计信息时是否使用统计首选项覆盖参数的输入值。 这样,您可以控制数据库何时接受传递给统计信息收集过程的参数值。

当 preference_overrides_parameter 设置为 FALSE(默认值)时,将接受统计信息收集过程的输入值。 当设置为 TRUE 时,输入值将被忽略。

使用 DBMS_STATS 中的 SET_TABLE_PREFS、SET_SCHEMA_PREFS 或 SET_GLOBAL_PREFS 过程设置 preference_overrides_parameter 首选项。 无论是否设置了preference_overrides_parameter,数据库都使用相同的优先顺序来设置统计信息(前面已经说过)

在此示例中,旧脚本显式设置了 estimate_percent,而不是使用推荐的 AUTO_SAMPLE_SIZE。 您的目标是阻止用户使用这些脚本在 sh.costs 表上设置首选项。

例1:

-- 没有为 sh.costs 或全局级别设置estimate_percent的首选项,因此首选项默认为 AUTO_SAMPLE_SIZE。
SELECT DBMS_STATS.GET_PREFS 
('estimate_percent', 'sh','costs') 
AS "STAT_PREFS" FROM DUAL;
 
STAT_PREFS
----------
DBMS_STATS.AUTO_SAMPLE_SIZE

-- 默认情况下,Oracle 数据库接受传递给 GATHER_*_STATS 过程的首选项。 要覆盖这些参数,您可以使用 SET_TABLE_PREFS 仅将成本表的 preference_overrides_parameter 首选项设置为 true。
EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'costs', 'preference_overrides_parameter', 'true');

-- 在收集 sh.costs 的统计信息时,您尝试将estimate_percent 设置为 100。 
-- 但是,由于此表的preference_overrides_parameter 为真,Oracle 数据库不支持estimate_percent=>100 设置。
-- 相反,数据库使用 AUTO_SAMPLE_SIZE 收集统计信息,这是默认设置。
EXEC DBMS_STATS.GATHER_TABLE_STATS('sh', 'costs', estimate_percent=>100);

-- 恢复默认设置
EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'costs', 'preference_overrides_parameter', 'false');

例2:在此示例中,您在全局级别将estimate_percent 设置为5,这意味着此首选项适用于数据库中未设置表首选项的每个表。 然后在 sh.sales 表上设置一个覆盖,该表没有设置表级首选项,以防止用户覆盖其脚本中的全局设置。

-- 没有为 sh.sales 或全局级别设置估计百分比的首选项,因此首选项默认为 AUTO_SAMPLE_SIZE。
SELECT DBMS_STATS.GET_PREFS 
('estimate_percent', 'sh','sales') 
AS "STAT_PREFS" FROM DUAL;
 
STAT_PREFS
----------
DBMS_STATS.AUTO_SAMPLE_SIZE

-- 您使用 SET_GLOBAL_PREFS 过程为数据库中没有设置表首选项的每个表将estimate_percent 首选项设置为 5。
EXEC DBMS_STATS.SET_GLOBAL_PREFS ('estimate_percent', '5');

-- 因为 sh.sales 没有首选项集,所以全局设置适用于此表。 现在查询 sh.sales 的首选项显示estimate_percent 设置为 5,这是全局设置。
SELECT DBMS_STATS.GET_PREFS ('estimate_percent', 'sh','sales') AS "STAT_PREFS" FROM DUAL;
STAT_PREFS
----------
5

-- 您使用 SET_TABLE_PREFS 仅将 sh.sales 表的 preference_overrides_parameter 首选项设置为 true。
EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'sales', 'preference_overrides_parameter', 'true');

-- 在收集 sh.sales 的统计信息时,您尝试将estimate_percent 设置为 10。 但是,因为对于 sales 表的 preference_overrides_parameter 为 true,并且因为定义了全局首选项,所以 Oracle 数据库实际上使用全局设置 5 来收集统计信息。
EXEC DBMS_STATS.GATHER_TABLE_STATS
('sh', 'sales', estimate_percent=>10);

-- 恢复默认值
EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'sales', 'preference_overrides_parameter', 'false');
EXEC DBMS_STATS.SET_GLOBAL_PREFS ('estimate_percent', DBMS_STATS.AUTO_SAMPLE_SIZE);

12.2.1.5 Setting Statistics Preferences: Example

此示例说明了 SET_TABLE_PREFS、SET_SCHEMA_STATS 和 SET_DATABASE_PREFS 之间的关系。

EXEC DBMS_STATS.SET_TABLE_PREFS ('sh', 'costs', 'incremental', 'false');

SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL;

STAT_PREFS 
----------
FALSE

EXEC DBMS_STATS.SET_SCHEMA_PREFS ('sh', 'incremental', 'true');

SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL;

STAT_PREFS
----------
TRUE

EXEC DBMS_STATS.SET_DATABASE_PREFS ('incremental', 'false');

SELECT DBMS_STATS.GET_PREFS ('incremental', 'sh', 'costs') AS "STAT_PREFS" FROM DUAL;

STAT_PREFS 
----------
FALSE

12.2.2 Setting Global Optimizer Statistics Preferences Using Cloud Control

略。

12.2.3 Setting Object-Level Optimizer Statistics Preferences Using Cloud Control

略。

12.2.4 Setting Optimizer Statistics Preferences from the Command Line

如果您不使用 Cloud Control 设置优化器统计首选项,那么您可以从命令行调用 DBMS_STATS 过程。

先决条件

此任务具有以下先决条件:

  • 要设置全局或数据库首选项,您必须具有 SYSDBA 权限,或者同时具有 ANALYZE ANY DICTIONARY 和 ANALYZE ANY 系统权限。
  • 要设置架构首选项,您必须以所有者身份连接,或者具有 SYSDBA 权限,或者具有 ANALYZE ANY 系统权限。
  • 要设置表首选项,您必须以表所有者身份连接或具有 ANALYZE ANY 系统特权。

示例:

SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', 'SH', 'SALES') FROM   DUAL;

DBMS_STATS.GET_PREFS('STALE_PERCENT','SH','SALES')                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
-----------------------------------------------------
10

EXEC DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'STALE_PERCENT', '13');

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 WHERE TABLE_NAME = 'SALES';

OWNER TABLE_NAME      PREFERENCE_NAME      PREFERENCE_VALUE              
----- --------------- -------------------- ------------------------------
SH    SALES           INCREMENTAL          FALSE                         
SH    SALES           PREFERENCE_OVERRIDES FALSE                         
                      _PARAMETER                                         

SH    SALES           STALE_PERCENT        13    

EXEC DBMS_STATS.DELETE_TABLE_PREFS('SH', 'SALES', 'STALE_PERCENT');

12.3 Configuring Options for Dynamic Statistics

动态统计是一种优化技术,其中数据库使用递归 SQL 来扫描表中块的小随机样本。

样本扫描估计谓词选择性。 使用这些估计,数据库为未分析的段确定更好的默认统计数据,并验证其估计。 默认情况下,当优化器统计信息丢失、过时或不足时,动态统计信息会在解析过程中自动运行递归 SQL 以扫描少量随机表块样本。

12.3.1 About Dynamic Statistics Levels

动态统计级别控制数据库何时收集动态统计信息,以及优化器用来收集统计信息的样本大小。

使用 OPTIMIZER_DYNAMIC_SAMPLING 初始化参数(默认为2)或语句提示设置动态统计级别。

注意:动态统计在早于 Oracle Database 12c 第 1 版 (12.1) 的版本中称为动态抽样。

下表描述了动态统计的级别。 请注意以下事项:

  • 如果启用了动态统计,那么当 SQL 语句使用并行执行时,数据库可能会选择使用动态统计。
  • 如果 OPTIMIZER_ADAPTIVE_STATISTICS 为 TRUE(默认为FASLE),则优化器在相关 SQL 计划指令存在时使用动态统计信息。 数据库在 SQL 计划指令存储中维护生成的统计信息,使它们可用于其他查询。

表 12-5 动态统计级别

级别优化器何时使用动态统计采样量(块)
0不使用动态统计。n/a
1对所有没有统计信息的表使用动态统计信息,但前提是满足以下条件:
- 查询中至少有一张非分区表没有统计信息。
- 该表没有索引。
- 该表的块数多于用于该表的动态统计的块数。
32
2如果语句中至少有一张表没有统计信息,使用动态统计信息。 这是默认值。64
3如果以下任一条件为真,使用动态统计:
- 语句中至少有一张表没有统计信息。
- 该语句在 WHERE 子句谓词中使用了一个或多个表达式,例如 WHERE SUBSTR(CUSTLASTNAME,1,3)。
64
4如果以下任一条件为真,使用动态统计:
- 语句中至少有一张表没有统计信息。
- 该语句在 WHERE 子句谓词中使用了一个或多个表达式,例如 WHERE SUBSTR(CUSTLASTNAME,1,3)。
- 该语句使用复杂谓词(同一表上多个谓词之间的 OR 或 AND 运算符)。
64
5标准与第 4 级相同,但数据库使用不同的样本量。128
6标准与第 4 级相同,但数据库使用不同的样本量。256
7标准与第 4 级相同,但数据库使用不同的样本量。512
8标准与第 4 级相同,但数据库使用不同的样本量。1024
9标准与第 4 级相同,但数据库使用不同的样本量。4086
10标准与第 4 级相同,但数据库使用不同的样本量。所有块
11标准与第 4 级相同,但数据库使用不同的样本量。自动确定

12.3.2 Setting Dynamic Statistics Levels Manually

确定对所有 SQL 语句都有益的数据库级设置可能很困难。

在设置动态统计级别时,Oracle 建议在会话级别设置 OPTIMIZER_DYNAMIC_SAMPLING 初始化参数。

本教程假定以下内容:

  • 您需要对以下查询进行正确的选择性估计,该查询在两个相关列上具有 WHERE 子句谓词:
  SELECT *
  FROM   sh.customers
  WHERE  cust_city='Los Angeles'
  AND    cust_state_province='CA';
  • 上述查询使用串行处理。
  • sh.customers 表包含满足查询条件的 932 行。
  • 您已经收集了关于 sh.customers 表的统计信息。
exec dbms_stats.gather_table_stats('sh', 'customers');
  • 您在 cust_city 和 cust_state_province 列上创建了一个索引。
create index CUST_CITY_STATE_IND on customers(cust_city, cust_state_province);
  • OPTIMIZER_DYNAMIC_SAMPLING 初始化参数设置为默认级别 2。
EXPLAIN PLAN FOR
  SELECT *
  FROM   sh.customers
  WHERE  cust_city='Los Angeles'
  AND    cust_state_province='CA';

SET LINESIZE 130
SET PAGESIZE 0
SELECT * 
FROM   TABLE(DBMS_XPLAN.DISPLAY);

-----------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                     |    57 | 10773 |    57   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| CUSTOMERS           |    57 | 10773 |    57   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | CUST_CITY_STATE_IND |    57 |       |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("CUST_CITY"='Los Angeles' AND "CUST_STATE_PROVINCE"='CA')

WHERE 子句中的列具有真实世界的相关性,但优化器不知道洛杉矶在加利福尼亚,并假设两个谓词都减少了返回的行数。 因此,该表包含 932 行满足条件,但优化器估计为 53,如以上计划所示。

如果数据库对该计划使用了动态统计信息,那么计划输出的“Notes”部分将表明这一事实。 优化器没有使用动态统计,因为语句串行执行,标准统计存在,参数 OPTIMIZER_DYNAMIC_SAMPLING 设置为默认值 2。

修改采样级别,这回估算准一些了。注意Note部分。

ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=4;

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |   555 |   102K|   424   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |   555 |   102K|   424   (1)| 00:00:01 |
-------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("CUST_CITY"='Los Angeles' AND "CUST_STATE_PROVINCE"='CA')
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=4)

如果将采用级别调整为10,则可以完全准确估计:

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |   932 |   172K|   424   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |   932 |   172K|   424   (1)| 00:00:01 |
-------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("CUST_CITY"='Los Angeles' AND "CUST_STATE_PROVINCE"='CA')
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=10)

最后,删除索引:

drop index CUST_CITY_STATE_IND;

12.3.3 Disabling Dynamic Statistics

一般来说,最好的做法是不要为编译时间必须尽可能快的查询(例如,不重复的 OLTP 查询)产生动态统计成本。
在会话级别禁用动态统计:

ALTER SESSION SET OPTIMIZER_DYNAMIC_SAMPLING=0;

12.4 Managing SQL Plan Directives

SQL 计划指令是优化器可以用来生成更优化计划的附加信息和指令。

一条指令通知数据库优化器错误估计了某些类型谓词的基数,并提醒 DBMS_STATS 在未来收集额外的统计信息。 因此,指令对统计数据收集有影响。

数据库在 SGA 中自动创建和管理 SQL 计划指令,然后定期将它们写入数据字典。 如果指令在 53 周内未使用,则数据库会自动清除它们。

您可以使用 DBMS_SPD 过程和函数手动更改、保存、删除和传输指令。 下表列出了一些较常用的过程和函数。

过程描述
FLUSH_SQL_PLAN_DIRECTIVE强制数据库将指令从内存写入 SYSAUX 表空间中的持久存储。
DROP_SQL_PLAN_DIRECTIVE删除 SQL 计划指令。 如果触发动态采样的指令产生了不可接受的性能开销,那么您可能需要手动删除它。
如果手动或自动删除 SQL 计划指令,则数据库可以重新创建它。 为防止其重新创建,您可以使用 DBMS_SPM.ALTER_SQL_PLAN_DIRECTIVE 执行以下操作:
- 通过将 ENABLED 设置为 NO 来禁用该指令
- 通过将 AUTO_DROP 设置为 NO 来防止指令被删除

要禁用 SQL 计划指令,请将 OPTIMIZER_ADAPTIVE_STATISTICS 设置为 FALSE。

先决条件:您必须具有管理 SQL 管理对象权限才能执行 DBMS_SPD API。

-- flush
exec DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE;

-- query
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;

-- delete
exec DBMS_SPD.DROP_SQL_PLAN_DIRECTIVE ( directive_id => 15138388896330674558 );

以上是关于SQL调优指南笔记12:Configuring Options for Optimizer Statistics Gathering的主要内容,如果未能解决你的问题,请参考以下文章

SQL调优指南笔记9:Joins

SQL调优指南笔记9:Joins

SQL调优指南笔记1:Introduction to SQL Tuning

SQL调优指南笔记6:Explaining and Displaying Execution Plans

SQL调优指南笔记11:Histograms

SQL调优指南笔记11:Histograms