Manage SQL Plan Baselines in Oracle 12c

使用dbms_spm与dbms_xplan包来执行大部分的SQL执行计划管理任务。SQL执行计划管理可以分为以下基本任务:
.配置SQL执行计划管理
.显示SQL执行计划基线中的执行计划
.加载SQL执行计划基线
.手动evolve执行计划基线中的执行计划
.删除SQL执行计划基线
.管理SQL Management Base(SMB)
.迁移Stored Outlines to SQL Plan Baselines

配置SQL执行计划管理
.配置捕获与使用SQL Plan Baselines
.管理SPM Evolve Advisor Task

配置捕获与使用SQL Plan Baselines
可以使用optimizer_capture_sql_plan_baselines与optimizer_use_sql_plan_baselines参数来控制SQL plan管理。

SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     TRUE

optimizer_capture_sql_plan_baselines的缺省值为false。对于不在执行计划历史中的任何重复的SQL语句,数据库不会对SQL语句自动创建一个初始的SQL Plan Baseline。如果optimizer_capture_sql_plan_baselines参数设置为true,那么可以使用dbms_spm.configure过程来配置过滤器来判断哪些SQL语句满足捕获条件。缺省情况是没有配置过滤器的,这意味着所有重复执行的SQL语句都满足捕获条件。

optimizer_use_sql_plan_baselines的缺省值为true。对于已经在SQL plan baseline中存在的任何SQL语句,数据库会自动向SQL plan baselines中以未接受的执行计划来添加新的SQL plan。

对SQL Plan管理启用自动初始化Plan捕获
将optimizer_capture_sql_plan_baselines参数设置为true是对在plan历史中不存在的任何SQL语句自动创建一个初始化SQL Plan baseline所必要的。缺省情况下,当自动SQL plan baseline捕获被启用后,数据库会为每个重复的SQL语句,包括所有递归SQL语句与监控SQL语句创建一个SQL Plan baseline。因此,自动捕获功能可能会造成大量的SQL Plan Baseline。 为了限制捕获的SQL Plan Baselines的数量可以使用dbms_spm.configure过程来配置过滤条件。optimizer_capture_sql_plan_baselines参数不控制自动向之前创建的SQL plan baseline添加新发现的执行计划。

启用自动捕获SQL plan baseline操作如下:
1.以有相关权限的用户用SQL*Plus登录数据库

[oracle@jytest1 ~]$ sqlplus sys/abcd@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Tue Feb 12 21:50:10 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

2.显示当前SQL Plan管理的设置情况

SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     TRUE

3.为了对重复的SQL语句启用自动生成SQL Plan Baseline执行下面的语句

SQL> alter system set optimizer_capture_sql_plan_baselines=true scope=both sid='*';

System altered.

SQL> show parameter optimizer_capture_sql_plan_baselines

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     TRUE

当启用SQL Plan Baselines自动捕获功能后可以从下面的结果看到对重复的所有SQL语句进行了执行执行的捕获

SQL> select t.sql_handle,t.sql_text,t.creator,t.origin from DBA_SQL_PLAN_BASELINES t;

SQL_HANDLE               SQL_TEXT                                                                         CREATOR   ORIGIN
------------------------ -------------------------------------------------------------------------------- --------- ---------------
SQL_187ebe987c151d1b     select value from v$nls_parameters where parameter = 'NLS_LENGTH_SEMANTICS'      SYS       AUTO-CAPTURE
SQL_65afdf280fbfa69f     select * from DBA_SQL_PLAN_BASELINES t                                           SYS       AUTO-CAPTURE
SQL_6807bab99db0361a     select value from v$sesstat where sid = :sid order by statistic#                 SYS       AUTO-CAPTURE

为自动SQL Plan Baseline捕获配置过滤条件
如果optimizer_capture_sql_plan_baselines设置为true,那么你可以使用dbms_spm.configure过程来对重复执行的SQL语句创建一个自动捕获过滤条件。自动过滤可以只捕获想要的SQL语句并排除非关键语句,这样可以节省SYSAUX表空间的使用。可以对不同的类型配置多个参数,也可以在单独的语句中对相同的参数指定多个参数值,数据库会进行组合。这种设置是附加型的:一个参数设置不会覆盖之前的设置。例如,下面的过滤设置用来捕获解析方案SYS或SYSTEM中的SQL语句:

exec dbms_spm.configure('auto_capture_parsing_schema_name','sys',true);
exec dbms_spm.configure('auto_capture_parsing_schema_name','system',true);

然而,不能在相同的过程中对相同的参数指定多个参数值。例如不能对AUTO_CAPTURE_SQL_TEXT指定多个SQL文本字符串。DBA_SQL_MANAGEMENT_CONFIG视图可以用来显示当前参数值。

下面的操作假设optimizer_capture_sql_plan_baselines参数被设置为true。只要捕获sh方案所有执行的SQL语句并且想要排除包含test_only文本的语句
1.以有相关权限的用户用SQL*Plus登录数据库

[oracle@jytest1 ~]$ sqlplus sys/abcd@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Tue Feb 12 21:50:10 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

2.为了删除对解析方案与SQL文本已经存在的任何过滤条件执行以下语句:

SQL> exec dbms_spm.configure('auto_capture_parsing_schema_name',null,true);

PL/SQL procedure successfully completed.

SQL> exec dbms_spm.configure('auto_capture_sql_text',null,true);

PL/SQL procedure successfully completed.

SQL> select parameter_name, parameter_value
  2  from dba_sql_management_config
  3  where parameter_name like '%AUTO%';

PARAMETER_NAME                   PARAMETER_VALUE
-------------------------------- --------------------------------
AUTO_CAPTURE_PARSING_SCHEMA_NAME
AUTO_CAPTURE_MODULE
AUTO_CAPTURE_ACTION
AUTO_CAPTURE_SQL_TEXT

3.只对sh方案所执行的语句启用自动捕获

SQL> exec dbms_spm.configure('auto_capture_parsing_schema_name','sh',true);

PL/SQL procedure successfully completed.

4.从自动捕获中排除任何包含test_only文本的语句

SQL> exec dbms_spm.configure('auto_capture_sql_text','%test_only%',false);

PL/SQL procedure successfully completed.

5.通过查询dba_sql_management_config视图来确认配置的过滤条件

SQL> col parameter_name format a32
SQL> col parameter_value format a32
SQL> select parameter_name, parameter_value
  2  from dba_sql_management_config
  3  where parameter_name like '%AUTO%';

PARAMETER_NAME                   PARAMETER_VALUE
-------------------------------- --------------------------------
AUTO_CAPTURE_PARSING_SCHEMA_NAME parsing_schema IN (SH)
AUTO_CAPTURE_MODULE
AUTO_CAPTURE_ACTION
AUTO_CAPTURE_SQL_TEXT            (sql_text NOT LIKE %test_only%)

禁用所有SQL Plan Baselines
当optimizer_use_sql_plan_baselines参数设置为false时,数据库不会使用任何SQL Plan Baseline。为了禁用所有SQL Plan baselines执行以下操作:
1.以有相关权限的用户用SQL*Plus登录数据库

[oracle@jytest1 ~]$ sqlplus sys/abcd@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Tue Feb 12 21:50:10 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production


SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     TRUE

2.为了忽略所有现存的SQL Plan Baselines执行以下语句

SQL> alter system set optimizer_use_sql_plan_baselines=false scope=both sid='*';

System altered.

SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     FALSE

管理SPM Evolve Advisor Task
SPM Evolve Advisor是一个SQL Advisor可以对最近添加到SQL Plan Baseline中的SQL Plan进行evolve。缺省情况下,SYS_AUTO_SPM_EVOLVE_TASK在调度维护窗口中每天运行。SPM Evolve Advisor Task执行以下操作:
1.定位未接受的SQL Plan
2.对所有未接受的SQL Plan进行排名
3.在维护窗口尽可能的对大量的SQL Plan进行测试执行
4.选择一个成本最低的执行计划与每个未接受的执行计划进行比较
5.使用基于成本的算法来自动接受比现有已接受的执行计划性能更好的任何未接受的执行计划

启用与禁用SPM Evolve Advisor Task
对于自动SPM Evolve Advisor Task没有单独的调度客户端存在。一个调度客户端控制着自动SQL Tuning Advisor与自动SPM Evolve Advisor。

配置自动SPM Evolve Advisor Task
通过使用dbms_spm.set_evolve_task_parameter过程来指定任务参数来配置自动SQL Plan Evolve。因为SYS_AUTO_SPM_EVOLVE_TASK任务的所有者为SYS,只有SYS用户可以设置任务参数。

dbms_spm.set_evolve_task_parameter有以下参数
alternate_plan_source:决定添加SQL Plan的搜索源:cursor_cache,automatic_workload_repository或sql_tuning_sets。可以使用+号来组合多个参数值,缺省值为cursor_cache+automatic_workload_repository

alternate_plan_baseline:决定那个替代plan应该被加载。EXISING它是缺省值,使用现有的SQL Plan baseline来为语句加载SQL plan。NEW不使用现有SQL plan baseline来为语句加载SQL plan,并且会创建一个新的SQL Plan baseline。可以使用+号来组合多个参数值。

alternate_plan_limit:指定可以加载SQL Plan的最大数量,缺省值为0。

accept_plans:指定是否自动接受建议的SQL Plan。当accept_plans设置为true(缺省值)时,SQL Plan管理自动接受由SPM Evolve Advisor Task所建议的所有SQL Plan。当设置为false时,如果找到替代的SQL plan,SPM Evolve Advisor Task会验证SQLPlan并生成一个报告,但不会evolve这个SQL plan。

下面的操作假如满足以下条件
.想要数据库自动接受SQL Plan
.想在任务每次执行1200秒后就会超时
.想要evolve任务在共享SQL区与AWR档案库中查找最多500个SQL Plan

设置自动evolve任务参数
1.以sys用户登录数据库

[oracle@jytest1 ~]$ sqlplus sys/abcd@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Tue Feb 12 21:50:10 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

2.查询sys_auto_spm_evolve_task任务的当前参数设置情况

SQL> col parameter_name format a25
SQL> col value format a42
SQL> select parameter_name, parameter_value as "value"
  2  from dba_advisor_parameters
  3  where ( (task_name = 'SYS_AUTO_SPM_EVOLVE_TASK') and
  4  ( (parameter_name = 'ACCEPT_PLANS') or
  5  (parameter_name LIKE '%ALT%') or
  6  (parameter_name = 'TIME_LIMIT') ) );

PARAMETER_NAME            value
------------------------- ------------------------------------------
TIME_LIMIT                3600
ALTERNATE_PLAN_LIMIT      10
ALTERNATE_PLAN_SOURCE     CURSOR_CACHE+AUTOMATIC_WORKLOAD_REPOSITORY
ALTERNATE_PLAN_BASELINE   EXISTING
ACCEPT_PLANS              TRUE

3.使用以下PLSQL块来配置sys_auto_spm_evolve_task任务自动接收SQL plan,在共享SQL区与AWR档案库中查找最多500个SQL plan,并且在执行20分钟后任务就会超时终止。

SQL> begin
  2  dbms_spm.set_evolve_task_parameter(task_name => 'SYS_AUTO_SPM_EVOLVE_TASK', parameter => 'TIME_LIMIT', value => '1200');
  3  dbms_spm.set_evolve_task_parameter(task_name => 'SYS_AUTO_SPM_EVOLVE_TASK', parameter => 'ACCEPT_PLANS', value => 'true');
  4  dbms_spm.set_evolve_task_parameter(task_name => 'SYS_AUTO_SPM_EVOLVE_TASK', parameter => 'ALTERNATE_PLAN_LIMIT', value => '500');
  5  end;
  6  /

PL/SQL procedure successfully completed.

4.确认sys_auto_spm_evolve_task任务的当前参数设置情况

SQL> col parameter_name format a25
SQL> col value format a42
SQL> select parameter_name, parameter_value as "value"
  2  from dba_advisor_parameters
  3  where ( (task_name = 'SYS_AUTO_SPM_EVOLVE_TASK') and
  4  ( (parameter_name = 'ACCEPT_PLANS') or
  5  (parameter_name LIKE '%ALT%') or
  6  (parameter_name = 'TIME_LIMIT') ) );

PARAMETER_NAME            value
------------------------- ------------------------------------------
TIME_LIMIT                1200
ALTERNATE_PLAN_LIMIT      500
ALTERNATE_PLAN_SOURCE     CURSOR_CACHE+AUTOMATIC_WORKLOAD_REPOSITORY
ALTERNATE_PLAN_BASELINE   EXISTING
ACCEPT_PLANS              true

显示SQL执行计划基线中的执行计划
为了查看指定SQL语句存储在SQL Plan Baseline中的SQL Plan,可以使用dbms_xplan.display_sql_plan_baseline 函数。这个函数使用存储在plan history中的执行计划信息来显示SQL Plan。它有以下参数:
sql_handle:语句的 SQL handle可以通过连接v$sql.sql_plan_baseline与dba_sql_plan_baselines.plan_name列来进行查询
plan_name:语句执行计划的名字

假设要显示SQL ID为34q7g1h49b79n的语句所存储在SQL Plan Baseline中的执行计划执行下面的语句

SQL> select * from hr.jobs;

JOB_ID     JOB_TITLE                           MIN_SALARY MAX_SALARY
---------- ----------------------------------- ---------- ----------
AD_PRES    President                                20080      40000
AD_VP      Administration Vice President            15000      30000
AD_ASST    Administration Assistant                  3000       6000
FI_MGR     Finance Manager                           8200      16000
FI_ACCOUNT Accountant                                4200       9000
AC_MGR     Accounting Manager                        8200      16000
AC_ACCOUNT Public Accountant                         4200       9000
SA_MAN     Sales Manager                            10000      20080
SA_REP     Sales Representative                      6000      12008
PU_MAN     Purchasing Manager                        8000      15000
PU_CLERK   Purchasing Clerk                          2500       5500

JOB_ID     JOB_TITLE                           MIN_SALARY MAX_SALARY
---------- ----------------------------------- ---------- ----------
ST_MAN     Stock Manager                             5500       8500
ST_CLERK   Stock Clerk                               2008       5000
SH_CLERK   Shipping Clerk                            2500       5500
IT_PROG    Programmer                                4000      10000
MK_MAN     Marketing Manager                         9000      15000
MK_REP     Marketing Representative                  4000       9000
HR_REP     Human Resources Representative            4000       9000
PR_REP     Public Relations Representative           4500      10500

19 rows selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  4gc64454ax64x, child number 1
-------------------------------------
select * from hr.jobs

Plan hash value: 944056911

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |
|   1 |  TABLE ACCESS FULL| JOBS |    19 |   627 |     3   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1 / JOBS@SEL$1

Outline Data
-------------

  /*+

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('optimizer_dynamic_sampling' 0)
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "JOBS"@"SEL$1")
      END_OUTLINE_DATA
  */

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "JOBS"."JOB_ID"[VARCHAR2,10], "JOBS"."JOB_TITLE"[VARCHAR2,35],
       "JOBS"."MIN_SALARY"[NUMBER,22], "JOBS"."MAX_SALARY"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel thre
shold

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   - SQL plan baseline SQL_PLAN_bmz5xhst6b31y41975532 used for this statement


45 rows selected.



SQL> SELECT PLAN_TABLE_OUTPUT
  2  FROM V$SQL s, DBA_SQL_PLAN_BASELINES b,
  3  TABLE(
  4  DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(b.sql_handle,b.plan_name,'basic')
  5  ) t
  6  WHERE s.EXACT_MATCHING_SIGNATURE=b.SIGNATURE
  7  AND b.PLAN_NAME=s.SQL_PLAN_BASELINE
  8  AND s.SQL_ID='4gc64454ax64x';

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SQL_b9fcbd8632658c3e
SQL text: select * from hr.jobs
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SQL_PLAN_bmz5xhst6b31y41975532         Plan id: 1100436786
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE
Plan rows: From dictionary
--------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Plan hash value: 944056911

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|   1 |  TABLE ACCESS FULL| JOBS |
----------------------------------

20 rows selected.

上面的结果显示SQL ID为4gc64454ax64x的执选执行计划名字叫SQL_PLAN_bmz5xhst6b31y41975532并且是被自动捕获的。

加载SQL执行计划基线
使用dbms_spm可以批量加载一组现有的执行计划到一个SQL Plan Baseline中。dbms_spm包可以从以下来源加载执行计划:
.AWR:要从AWR快照加载执行计划,那么必须指定快照开始与结束的范围,另外也可以应用过滤条件来只加载满足条件的执行计划。缺省情况下,数据库在下一次执行SQL语句时优化器就会使用加载到SQL Plan Baseline中的执行计划。

.共享SQL区:直接从共享SQL区来加载执行计划。通过对模块名,方案名或SQL ID应用过滤条件可以标识需要被捕获的SQL语句或一组SQL语句。数据库在下一次执行SQL语句时优化器就会使用加载到SQL Plan Baseline中的执行计划。当应用程序SQL已经通过手写hints进行过优化之后直接从共享SQL区中加载执行计划是非常有用的。因为你可能不能更改SQL包括hint,使用SQL Plan Baseline可以确保应用程序SQL使用最优的执行计划。

.SQL tuning set(STS):捕获SQL工作量的执行计划到一个STS中,然后加载执行计划到SQL Plan Baselines中。数据库在下一次执行SQL语句时优化器就会使用加载到SQL Plan Baseline中的执行计划。从STS中批量加载执行计划是在数据库升级后防止执行计划回归有效的方法。

.Staging table:使用dbms_spm包可以定义一个staging表,dbms_spm.pack_stgtab_baseline过程可以复制SQLPlan baseline到一个staging表中,并使用Oracle data pump将共staging表传输到另一个数据库。在目标数据库中,使用dbms_spm.unpack_stgtab_baseline过程来从staging表中把SQL plan baseline加载到SMB中。

.Stored outline:迁移stroed outlines到SQL Plan Baselines中。在迁移之后,你可以通过SQL Plan管理所提供的更高级的功能来维护相同的执行计划稳定性。

从AWR加载执行计划
假设我们要将下面的查询语句的执行计划加载到SQL Plan Baseline中,那么要确保用户sh有查询dba_hist_snapshot和dba_sql_plan_baselines视图,执行dbms_workload_repository.create_snapshot和dbms_spm.load_plans_from_awr的权限

SELECT /*LOAD_AWR*/ *
FROM sh.sales
WHERE quantity_sold > 40
ORDER BY prod_id;

为了从AWR中加载执行计划到SQL Plan Baselines中执行以下操作
1.以有相关权限的用户登录到数据库,然后查询最近生成的3个AWR快照

SQL> select *
  2  from (select instance_number,snap_id, snap_level,
  3  to_char(begin_interval_time, 'dd/mm/yy hh24:mi:ss') begin
  4  from dba_hist_snapshot
  5  order by snap_id desc)
  6  where rownum < = 3;

INSTANCE_NUMBER    SNAP_ID SNAP_LEVEL BEGIN
--------------- ---------- ---------- -----------------
              1       7061          1 14/02/19 16:00:09
              2       7061          1 14/02/19 16:00:09
              1       7060          1 14/02/19 15:00:35

2.查询sh.sales表,使用load_awr标记来识别这个SQL语句

SQL> select /*load_awr*/ *
  2  from sh.sales
  3  where quantity_sold > 40
  4  order by prod_id;

no rows selected

3.生成一个新的AWR快照

SQL> exec dbms_workload_repository.create_snapshot;

PL/SQL procedure successfully completed.

4.查询最近生成的3个AWR快照来确保新的AWR快照已经生成了

SQL> select *
  2  from (select instance_number,snap_id, snap_level,
  3  to_char(begin_interval_time, 'dd/mm/yy hh24:mi:ss') begin
  4  from dba_hist_snapshot
  5  order by snap_id desc)
  6  where rownum < = 3;

INSTANCE_NUMBER    SNAP_ID SNAP_LEVEL BEGIN
--------------- ---------- ---------- -----------------
              1       7062          1 14/02/19 17:00:09
              2       7062          1 14/02/19 17:00:09
              1       7061          1 14/02/19 16:00:09

5.使用最近生成的2个AWR快照来加载执行计划

SQL> variable v_plan_cnt number
SQL> exec :v_plan_cnt := dbms_spm.load_plans_from_awr(begin_snap => 7061, end_snap =>7062);

PL/SQL procedure successfully completed.

6.查询数据字典来确保load_awr语句的执行计划被加载到SQL Plan Baselines中了

SQL> col sql_handle format a20
SQL> col sql_text format a20
SQL> col plan_name format a30
SQL> col origin format a20
SQL> select sql_handle, sql_text, plan_name,
  2  origin, enabled, accepted
  3  from dba_sql_plan_baselines
  4  where sql_text like '%load_awr%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---

SQL_495d29c5f4612cda select /*load_awr*/  SQL_PLAN_4kr99sru62b6u54bc8843 MANUAL-LOAD-FROM-AWR YES YES
                     *
                     from sh.sales
                     where quantity_sold
                     > 40
                     order by prod_id

7.再次执行load_awr语句,查看其执行计划可以看到SQL plan baseline SQL_PLAN_4kr99sru62b6u54bc8843 used for this statement这样的信息,说明生成的执行计划基线应用到该语句了

SQL> select /*load_awr*/ *
  2  from sh.sales
  3  where quantity_sold > 40
  4  order by prod_id;

no rows selected

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------
SQL_ID  dybku83zppk0d, child number 1
-------------------------------------
select /*load_awr*/ * from sh.sales where quantity_sold > 40 order by
prod_id

Plan hash value: 3803407550

----------------------------------------------------------------------------------------------
| Id  | Operation            | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |       |       |       |   511 (100)|          |       |       |
|   1 |  SORT ORDER BY       |       |     1 |    29 |   511   (2)| 00:00:01 |       |       |
|   2 |   PARTITION RANGE ALL|       |     1 |    29 |   510   (2)| 00:00:01 |     1 |    28 |
|*  3 |    TABLE ACCESS FULL | SALES |     1 |    29 |   510   (2)| 00:00:01 |     1 |    28 |
----------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   3 - SEL$1 / SALES@SEL$1
Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('optimizer_dynamic_sampling' 0)
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "SALES"@"SEL$1")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("QUANTITY_SOLD">40)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=1) "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22],
       "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22],
       "SALES"."PROMO_ID"[NUMBER,22], "SALES"."QUANTITY_SOLD"[NUMBER,22],
       "SALES"."AMOUNT_SOLD"[NUMBER,22]
   2 - (rowset=256) "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22],
       "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22],
       "SALES"."PROMO_ID"[NUMBER,22], "QUANTITY_SOLD"[NUMBER,22],
       "SALES"."AMOUNT_SOLD"[NUMBER,22]
   3 - (rowset=256) "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22],
       "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22],
       "SALES"."PROMO_ID"[NUMBER,22], "QUANTITY_SOLD"[NUMBER,22],
       "SALES"."AMOUNT_SOLD"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
   - SQL plan baseline SQL_PLAN_4kr99sru62b6u54bc8843 used for this statement


64 rows selected.

从共享SQL区加载执行计划
假设要从共享SQL区将下面的查询语句的执行计划加载到SQL Plan Baseline中需要执行以下操作
1.执行SQL语句

SQL> SELECT /*LOAD_CC*/ *
  2  FROM sh.sales
  3  WHERE quantity_sold > 40
  4  ORDER BY prod_id;

no rows selected

2.查询v$sql视图查询执行语句的SQL ID

SQL> SELECT SQL_ID, CHILD_NUMBER AS "Child Num",
  2  PLAN_HASH_VALUE AS "Plan Hash",
  3  OPTIMIZER_ENV_HASH_VALUE AS "Opt Env Hash"
  4  FROM V$SQL
  5  WHERE SQL_TEXT LIKE 'SELECT /*LOAD_CC*/%';

SQL_ID         Child Num  Plan Hash Opt Env Hash
------------- ---------- ---------- ------------
09x8cz4wrn655          0 3803407550   4099961812

3.从共享SQL区加载指定语句的执行计划到SQL Plan Baseline中

SQL> VARIABLE v_plan_cnt NUMBER
SQL> EXECUTE :v_plan_cnt := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id =>'09x8cz4wrn655');

PL/SQL procedure successfully completed.

4.查询dba_sql_plan_baselines视图来确认语句的执行计划是否加载到SQL Plan Baselines中了

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED
  3  FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%LOAD_CC%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_f6cb7f742ef93547 SELECT /*LOAD_CC*/ * SQL_PLAN_gdkvzfhrgkda754bc8843 MANUAL-LOAD-FROM-CUR YES YES
                                                                         SOR-CACHE
                     FROM sh.sales
                     WHERE quantity_sold
                     > 40
                     ORDER BY prod_id

从SQL Tuning Set中加载执行计划
一个SQL Tuning Set是一个数据库对象它包括一个或多个SQL语句,执行统计信息与执行上下文信息。假设SQLTuning Set包含下面的语句,要从SQL Tuning Set中加载该语句的执行计划到SQL Plan Baselines中要执行以下操作
1.执行SQL语句并找到其SQL ID

SQL> SELECT /*LOAD_STS*/ *
  2  FROM sh.sales
  3  WHERE quantity_sold > 40
  4  ORDER BY prod_id;

no rows selected

SQL> SELECT SQL_ID, CHILD_NUMBER AS "Child Num",
  2  PLAN_HASH_VALUE AS "Plan Hash",
  3  OPTIMIZER_ENV_HASH_VALUE AS "Opt Env Hash"
  4  FROM V$SQL
  5  WHERE SQL_TEXT LIKE 'SELECT /*LOAD_STS*/%';

SQL_ID         Child Num  Plan Hash Opt Env Hash
------------- ---------- ---------- ------------
bma11r5a6r26j          0 3803407550   4099961812

2.将执行的SQL语句加载到SQL Tuning Set中

SQL> exec dbms_sqltune.create_sqlset(sqlset_name=>'sql_tuning_set');

PL/SQL procedure successfully completed.

SQL> DECLARE
  2    cur DBMS_SQLTUNE.SQLSET_CURSOR;
  3  BEGIN
  4    OPEN cur FOR
  5      SELECT VALUE(P)
  6        FROM table(DBMS_SQLTUNE.SELECT_CURSOR_CACHE('sql_id=''bma11r5a6r26j''',
  7                                                    NULL,
  8                                                    NULL,
  9                                                    NULL,
 10                                                    NULL,
 11                                                    1,
 12                                                    NULL,
 13                                                    'ALL')) P;
 14    DBMS_SQLTUNE.LOAD_SQLSET(sqlset_name     => 'sql_tuning_set',
 15                             populate_cursor => cur);
 16  END;
 17  /

PL/SQL procedure successfully completed.



SQL> SELECT SQL_TEXT FROM DBA_SQLSET_STATEMENTS WHERE SQLSET_NAME = 'sql_tuning_set';

SQL_TEXT
--------------------
SELECT /*LOAD_STS*/
*
FROM sh.sales
WHERE quantity_sold
> 40
ORDER BY prod_id

3.从SQL Tuning Set中加载执行计划到SQL Plan Baseline中

SQL> VARIABLE v_plan_cnt NUMBER
SQL> EXECUTE :v_plan_cnt := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(sqlset_name => 'sql_tuning_set',basic_filter => 'sql_text like ''SELECT /*LOAD_STS*/%''' );

PL/SQL procedure successfully completed.

basic_filter参数指定了一个where子句用来只加载需要的SQL语句,v_plan_cnt用来存储从SQL Tuning Set所加载的执行计划数。

4.查询数据字典来确保SQL Tuning Set中的语句的执行计划是否成功加载到SQL Plan Baselines中

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED
  3  FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%LOAD_STS%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_a8632bd857a4a25e SELECT /*LOAD_STS*/  SQL_PLAN_ahstbv1bu98ky54bc8843 MANUAL-LOAD-FROM-STS YES YES
                     *
                     FROM sh.sales
                     WHERE quantity_sold
                     > 40
                     ORDER BY prod_id

5.删除SQL Tuning Set

SQL> exec dbms_sqltune.drop_sqlset(sqlset_name=>'sql_tuning_set');

PL/SQL procedure successfully completed.

从Staging Table中加载执行计划
有时可能需要从一个源数据库传输最优化的执行计划到一个目标数据库那么需要执行以下操作
1.使用create_stgtab_baseline过程来创建一个staging表

SQL> BEGIN
  2  DBMS_SPM.CREATE_STGTAB_BASELINE (
  3  table_name => 'stage1');
  4  END;
  5  /

PL/SQL procedure successfully completed.

2.在源数据库中,将SQL Plan Baseline从SQL管理基础框架中打包到staging表中

DECLARE
v_plan_cnt NUMBER;
BEGIN
v_plan_cnt := DBMS_SPM.PACK_STGTAB_BASELINE (
table_name => 'stage1'
, enabled => 'yes'
, creator => 'spm'
);
END;
/

3.将staging表stage1使用Oracle Data Pump Export导出到一个dump文件中

4.将dump文件传输到目标数据库

5.在目标数据库中,使用Oracle Data Pump Import将dump文件中的数据导入到staging表stage1中

6.在目标数据库中,将SQL Plan Baseline从staging表中解压到SQL管理基础框架中

DECLARE
v_plan_cnt NUMBER;
BEGIN
v_plan_cnt := DBMS_SPM.UNPACK_STGTAB_BASELINE (
table_name => 'stage1'
, fixed => 'yes'
);
END;
/

SQL Plan baselines Evolve
这里将介绍如何使用命令行来evolve sql plan baselines。为了evolve一个特定的sql执行计划执行以下操作:
1.创建一个evolve任务
2.设置evolve任务参数
3.执行evolve任务
4.实现任务中给出的建议
5.显示任务执行的结果

下面将举例来说明,假设满足以下条件
.数据库没有启用自动evolve任务
.对下面的查询创建一个SQL Plan Baseline

SELECT /* q2_group_by */ prod_name, sum(quantity_sold)
FROM products p, sales s
WHERE p.prod_id = s.prod_id
AND p.prod_category_id =204
GROUP BY prod_name;

.想要创建两个索引来提高查询语句的性能,如果使用索引的性能比SQL Plan Baseline中的当前执行计划的性能好那么就evolve该执行计划

为了evolve一个特定的执行计划需要执行以下操作
1.执行初始化设置操作

清空共享池与缓冲区缓存

SQL> ALTER SYSTEM FLUSH SHARED_POOL;

System altered.

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

启用自动捕获SQL Plan Baselines

SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=true;

System altered.

SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     TRUE
optimizer_use_sql_plan_baselines     boolean     TRUE

以sh用户登录到数据库,然后设置SQLPLUS的显示参数

[oracle@jytest1 ~]$ sqlplus sh/sh@jypdb

SQL*Plus: Release 12.2.0.1.0 Production on Thu Feb 14 23:30:09 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Last Successful login time: Thu Feb 14 2019 23:01:23 +08:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production


SQL> SET PAGES 10000 LINES 140
SQL> SET SERVEROUTPUT ON
SQL> COL SQL_TEXT FORMAT A20
SQL> COL SQL_HANDLE FORMAT A20
SQL> COL PLAN_NAME FORMAT A30
SQL> COL ORIGIN FORMAT A12
SQL> SET LONGC 60535
SQL> SET LONG 60535
SQL> SET ECHO ON

2.执行SQL语句,因此可以自动捕获它
执行下面的SQL语句

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

查询数据字典确认在SQL Plan Baseline中不存在执行计划,因为只有重复执行的SQL语句才会被捕获

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED,
  2  ACCEPTED, FIXED, AUTOPURGE
  3  FROM DBA_SQL_PLAN_BASELINES
  4  WHERE SQL_TEXT LIKE '%q1_group%';

no rows selected

再次执行SQL语句

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

3.查询数据字典来确保执行计划已经被加载到SQL Plan Baseline中了,下面的查询显示执行计划已经被接受,这意味着执行计划已经存储在SQL Plan Baselines中了。origin列显示为AUTO-CAPTURE,这意味着执行计划是被自动捕获的

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED, FIXED
  3  FROM DBA_SQL_PLAN_BASELINES
  4  WHERE SQL_TEXT LIKE '%q1_group%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN       ENA ACC FIX
-------------------- -------------------- ------------------------------ ------------ --- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE YES YES NO
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

4.下面对SQL语句进行解析并验证优化器是否会使用SQL Plan Baseline中的执行计划

SQL> EXPLAIN PLAN FOR
  2  SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  3  FROM products p, sales s
  4  WHERE p.prod_id = s.prod_id
  5  AND p.prod_category_id =203
  6  GROUP BY prod_name;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(null, null, 'basic +note'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3535171836

------------------------------------------
| Id  | Operation             | Name     |
------------------------------------------
|   0 | SELECT STATEMENT      |          |
|   1 |  HASH GROUP BY        |          |
|   2 |   HASH JOIN           |          |
|   3 |    TABLE ACCESS FULL  | PRODUCTS |
|   4 |    PARTITION RANGE ALL|          |
|   5 |     TABLE ACCESS FULL | SALES    |
------------------------------------------

Note
-----
   - SQL plan baseline "SQL_PLAN_0gwbcfvzskcu242949306" used for this statement

16 rows selected.

从执行计划的Note部分可以看到SQL Plan Baseline已经应用到这个SQL语句了

5.创建两个索引用来提高上面SQL语句的性能

SQL> CREATE INDEX ind_prod_cat_name ON products(prod_category_id, prod_name, prod_id);

Index created.

SQL> CREATE INDEX ind_sales_prod_qty_sold ON sales(prod_id, quantity_sold);

Index created.

6.再次执行SQL语句,因为启用了自动捕获功能,所以新的执行计划会被加载到SQL Plan Baseline中

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

7.查询数据字典来确保新的执行计划被加载到SQL Plan Baseline中了

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED
  2  FROM DBA_SQL_PLAN_BASELINES
  3  WHERE SQL_HANDLE IN ('SQL_07f16c76ff893342')
  4  ORDER BY SQL_HANDLE, ACCEPTED;

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN       ENA ACC
-------------------- -------------------- ------------------------------ ------------ --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu20135fd6c AUTO-CAPTURE YES NO
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

上面的查询结果显示新的执行计划是为被接受的。

8.再次解析SQL语句并验证优化器是不是使用原始没有索引的执行计划

SQL> EXPLAIN PLAN FOR
  2  SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  3  FROM products p, sales s
  4  WHERE p.prod_id = s.prod_id
  5  AND p.prod_category_id =203
  6  GROUP BY prod_name;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(null, null, 'basic +note'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3535171836

------------------------------------------
| Id  | Operation             | Name     |
------------------------------------------
|   0 | SELECT STATEMENT      |          |
|   1 |  HASH GROUP BY        |          |
|   2 |   HASH JOIN           |          |
|   3 |    TABLE ACCESS FULL  | PRODUCTS |
|   4 |    PARTITION RANGE ALL|          |
|   5 |     TABLE ACCESS FULL | SALES    |
------------------------------------------

Note
-----
   - SQL plan baseline "SQL_PLAN_0gwbcfvzskcu242949306" used for this statement

16 rows selected.

上面的Note部分指示优化器使用了原始的没有索引的执行计划

9.以管理员用户登录数据库,然后创建一个evolve任务它包含未被接受执行计划相关的所有SQL语句

[oracle@jytest1 ~]$ sqlplus sys/xxzx7817600@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Thu Feb 14 23:48:51 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> VARIABLE cnt NUMBER
SQL> VARIABLE tk_name VARCHAR2(50)
SQL> VARIABLE exe_name VARCHAR2(50)
SQL> VARIABLE evol_out CLOB
SQL> EXECUTE :tk_name := DBMS_SPM.CREATE_EVOLVE_TASK(sql_handle => 'SQL_07f16c76ff893342',plan_name => 'SQL_PLAN_0gwbcfvzskcu20135fd6c');

PL/SQL procedure successfully completed.

SQL> SELECT :tk_name FROM DUAL;

:TK_NAME
--------------------------------------------------------------------------------------------------------------------------------
TASK_11

10.执行evolve任务

SQL>EXECUTE :exe_name :=DBMS_SPM.EXECUTE_EVOLVE_TASK(task_name=>:tk_name);
PL/SQL procedure successfully completed.

SQL>SELECT :exe_name FROM DUAL;
:EXE_NAME
---------------------------------------------------------------------------
EXEC_1

11.查看报告

EXECUTE :evol_out := DBMS_SPM.REPORT_EVOLVE_TASK( task_name=>:tk_name,
execution_name=>:exe_name );
SELECT :evol_out FROM DUAL;
GENERAL INFORMATION SECTION
--------------------------------------------------------------------------
Task Information:
---------------------------------------------
Task Name : TASK_11
Task Owner : SYS
Execution Name : EXEC_1
Execution Type       : SPM EVOLVE
Scope                : COMPREHENSIVE
Status               : COMPLETED
Started              : 02/15/2019 17:49:32
Finished             : 02/15/2019 17:49:35
Last Updated         : 02/15/2019 17:49:35
Global Time Limit    : 2147483646
Per-Plan Time Limit  : UNUSED
Number of Errors     : 0
---------------------------------------------------------------------------
SUMMARY SECTION
---------------------------------------------------------------------------
Number of plans processed : 1
Number of findings : 1
Number of recommendations : 1
Number of errors : 0
---------------------------------------------------------------------------
DETAILS SECTION
---------------------------------------------------------------------------
Object ID : 2
Test Plan Name : SQL_PLAN_0gwbcfvzskcu20135fd6c
Base Plan Name : SQL_PLAN_0gwbcfvzskcu242949306
SQL Handle : SQL_07f16c76ff893342
Parsing Schema : SH
Test Plan Creator : SH
SQL Text : SELECT /*q1_group_by*/ prod_name,
sum(quantity_sold)
FROM products p, sales s
WHERE p.prod_id=s.prod_id AND p.prod_category_id=203
GROUP BY prod_name
Execution Statistics:
-----------------------------
Base Plan Test Plan
---------------------------- ------------------------
Elapsed Time (s): .044336 .012649
CPU Time (s): .044003 .012445
Buffer Gets: 360 99
Optimizer Cost: 924 891
Disk Reads: 341 82
Direct Writes: 0 0
Rows Processed: 4 2
Executions: 5 9
FINDINGS SECTION
---------------------------------------------------------------------------
Findings (1):
-----------------------------
1. The plan was verified in 2.18 seconds. It passed the benefit criterion
because its verified performance was 2.01 times better than that of the
baseline plan.
Recommendation:
-----------------------------
Consider accepting the plan. Execute
dbms_spm.accept_sql_plan_baseline(task_name => 'TASK_11', object_id => 2,
task_owner => 'SYS');
EXPLAIN PLANS SECTION
---------------------------------------------------------------------------
Baseline Plan
-----------------------------
Plan Id : 1
Plan Hash Value : 1117033222
---------------------------------------------------------------------------
| Id| Operation               | Name     | Rows | Bytes   |Cost | Time    |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT        |          |   21 |     861 | 924 | 00:00:12|
| 1 |   HASH GROUP BY         |          |   21 |     861 | 924 | 00:00:12|
| *2|    HASH JOIN            |          |267996|10987836 | 742 | 00:00:09|
| *3|     TABLE ACCESS FULL   | PRODUCTS |   21 |     714 |   2 | 00:00:01|
| 4 |     PARTITION RANGE ALL |          |918843| 6431901 | 662 | 00:00:08|
| 5 |      TABLE ACCESS FULL  | SALES    |918843| 6431901 | 662 | 00:00:08|
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access("P"."PROD_ID"="S"."PROD_ID")
* 3 - filter("P"."PROD_CATEGORY_ID"=203)
Test Plan
-----------------------------
Plan Id : 2
Plan Hash Value : 20315500
---------------------------------------------------------------------------
|Id| Operation           | Name             | Rows | Bytes  | Cost| Time   |
---------------------------------------------------------------------------
| 0|SELECT STATEMENT     |                  |    21|     861|  891|00:00:11|
| 1| SORT GROUP BY NOSORT|                  |    21|     861|  891|00:00:11|
| 2|  NESTED LOOPS       |                  |267996|10987836|  891|00:00:11|
|*3|   INDEX RANGE SCAN  |IND_PROD_CAT_NAME |    21|     714|    1|00:00:01|
|*4|   INDEX RANGE SCAN  |IND_SALES_PROD_QTY| 12762|   89334|   42|00:00:01|
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("P"."PROD_CATEGORY_ID"=203)
* 4 - access("P"."PROD_ID"="S"."PROD_ID")

报告显示使用两个索引的执行计划比原始执行计划性能更好

12.实现evolve任务所给出的建议

SQL>EXECUTE :cnt := DBMS_SPM.IMPLEMENT_EVOLVE_TASK( task_name=>:tk_name,execution_name=>:exe_name );
PL/SQL procedure successfully completed.

13.查询数据字典来确保新的执行计划已经是接受状态

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED
  2  FROM DBA_SQL_PLAN_BASELINES
  3  WHERE SQL_HANDLE IN ('SQL_07f16c76ff893342')
  4  ORDER BY SQL_HANDLE, ACCEPTED;

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE         YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name


SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu2ae9b4305 AUTO-CAPTURE         YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

14.执行清除操作

SQL> VARIABLE cnt NUMBER
SQL> EXEC :cnt := DBMS_SPM.DROP_SQL_PLAN_BASELINE('SQL_07f16c76ff893342');

PL/SQL procedure successfully completed.


SQL> DELETE FROM SQLLOG$;

13 rows deleted.

SQL> commit;

Commit complete.


SQL> DROP INDEX IND_SALES_PROD_QTY_SOLD;
Index dropped.



SQL> DROP INDEX IND_PROD_CAT_NAME;

Index dropped.

删除SQL Plan Baselines
可以从SQL Plan Baselines中删除一些或所有执行计划。

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED
  3  FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%q3_group_by%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_50c02f29322b0d02 SELECT SQL_HANDLE, S SQL_PLAN_51h1g54t2q38276fe3bd1 AUTO-CAPTURE         YES YES
                     QL_TEXT, PLAN_NAME,
                     ORIGIN, ENABLED, ACC
                     EPTED
                     FROM DBA_SQL_PLAN_BA
                     SELINES WHERE SQL_TE
                     XT LIKE '%q3_group_b
                     y%'

SQL_6d39c79190585ca9 SELECT /* q3_group_b SQL_PLAN_6uff7k685hr5942949306 AUTO-CAPTURE         YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =205
                     GROUP BY prod_name

SQL_6d39c79190585ca9 SELECT /* q3_group_b SQL_PLAN_6uff7k685hr59ae9b4305 AUTO-CAPTURE         YES NO
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =205
                     GROUP BY prod_name


SQL> DECLARE
  2  v_dropped_plans number;
  3  BEGIN
  4   v_dropped_plans := DBMS_SPM.DROP_SQL_PLAN_BASELINE(sql_handle => 'SQL_6d39c79190585ca9');
  5   DBMS_OUTPUT.PUT_LINE('dropped ' || v_dropped_plans || ' plans');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED
  3  FROM DBA_SQL_PLAN_BASELINES WHERE SQL_HANDLE='SQL_6d39c79190585ca9';

no rows selected

管理SQL Management Base
SQL Management Base是数据字典的一部分,它存储在SYSAUX表空间中。它存储语句日志,执行计划历史记录,SQL执行计划基线与SQL Profiles。使用dbms_spm.configure过程可以对SMB进行选项设置与维护SQL Plan Baselines。dba_sql_management_config视图可以用来查看SMB的当前配置信息。下面介绍parameter_name列可以设置的参数列表:
space_budget_percent:SQL Management Base可以使用的SYSAUX表空间的最大百分比。缺省值是10%。允许的范围是1%到50%。

plan_retention_weeks:在清除之前没有被使用的执行计划需要保留多少周,缺省值是53。

auto_capture_parsing_schema_name:它是(% LIKE a OR % LIKE b …) AND (%NOT LIKE c AND % NOT LIKE d …)形式的列表,它代表了解析方案名过滤。

auto_capture_module:它是(% LIKE a OR % LIKE b …) AND (%NOT LIKE c AND % NOT LIKE d …)形式的列表,它代表了模块过滤。

auto_capture_action:它是(% LIKE a OR % LIKE b …) AND (%NOT LIKE c AND % NOT LIKE d …)形式的列表,它代表了操作过滤。

auto_capture_sql_text:它是(% LIKE a OR % LIKE b …) AND (%NOT LIKE c AND % NOT LIKE d …)形式的列表,它代表了SQL文本过滤。

修改SMB空间使用限制
一个由SMB所调用的每周运行一次的后台进程将会检测空间使用情况。当超过定义限制时,后台进程将会写一个告警信息到alert日志文件中。数据库会每周生成一个告警信息直到SMB空间限制被增加为止,SYSAUX表空间被增加为止或者通过清除SQL Management对象(sql plan baselines或sql profiles)来减少SMB所使用的空间为止。

1.查看当前SMB所用空间的限制大小,从查询结果可以看到当前大小是SYSAUX表空间大小的10%

SQL> col parameter_name for a30
SQL> col %_LIMIT for a20
SQL> SELECT PARAMETER_NAME, PARAMETER_VALUE AS "%_LIMIT",
  2  ( SELECT sum(bytes/1024/1024) FROM DBA_DATA_FILES
  3  WHERE TABLESPACE_NAME = 'SYSAUX' ) AS SYSAUX_SIZE_IN_MB,
  4  PARAMETER_VALUE/100 *
  5  ( SELECT sum(bytes/1024/1024) FROM DBA_DATA_FILES
  6  WHERE TABLESPACE_NAME = 'SYSAUX' ) AS "CURRENT_LIMIT_IN_MB"
  7  FROM DBA_SQL_MANAGEMENT_CONFIG
  8  WHERE PARAMETER_NAME = 'SPACE_BUDGET_PERCENT';

PARAMETER_NAME                 %_LIMIT              SYSAUX_SIZE_IN_MB CURRENT_LIMIT_IN_MB
------------------------------ -------------------- ----------------- -------------------
SPACE_BUDGET_PERCENT           10                                1260                 126

2.将SMB所用空间限制大小修改为SYSAUX表空间大小的30%

SQL> EXECUTE DBMS_SPM.CONFIGURE('space_budget_percent',30);

PL/SQL procedure successfully completed.

3.确认SMB所有空间限制大小是否成功被修改为SYSAUX表空间大小的30%

SQL> SELECT PARAMETER_NAME, PARAMETER_VALUE AS "%_LIMIT",
  2  ( SELECT sum(bytes/1024/1024) FROM DBA_DATA_FILES
  3  WHERE TABLESPACE_NAME = 'SYSAUX' ) AS SYSAUX_SIZE_IN_MB,
  4  PARAMETER_VALUE/100 *
  5  ( SELECT sum(bytes/1024/1024) FROM DBA_DATA_FILES
  6  WHERE TABLESPACE_NAME = 'SYSAUX' ) AS "CURRENT_LIMIT_IN_MB"
  7  FROM DBA_SQL_MANAGEMENT_CONFIG
  8  WHERE PARAMETER_NAME = 'SPACE_BUDGET_PERCENT';

PARAMETER_NAME                 %_LIMIT              SYSAUX_SIZE_IN_MB CURRENT_LIMIT_IN_MB
------------------------------ -------------------- ----------------- -------------------
SPACE_BUDGET_PERCENT           30                                1260                 378

修改SMB中的Plan Retention Policy
每周调度清除任务来管理由SQL Plan Management所使用的空间。这个任务是一个在维护窗口内自动执行的任务。数据库会自动清除超过Plan Retention期限而没有被使用的执行计划,它是执行计划存储在SMB中的last_executed字段来标识的。缺生活上的执行计划保留周期是53周。这个周期可以设置的范围是5到523周。

1.查看当前执行计划保留周期

SQL> SELECT PARAMETER_NAME, PARAMETER_VALUE
  2  FROM DBA_SQL_MANAGEMENT_CONFIG
  3  WHERE PARAMETER_NAME = 'PLAN_RETENTION_WEEKS';

PARAMETER_NAME                 PARAMETER_
------------------------------ ----------
PLAN_RETENTION_WEEKS           53

2.修改执行计划保留周期为105周

SQL> EXECUTE DBMS_SPM.CONFIGURE('plan_retention_weeks',105);

PL/SQL procedure successfully completed.

3.确保执行计划保留周期是否成功被修改为105周

SQL> SELECT PARAMETER_NAME, PARAMETER_VALUE
  2  FROM DBA_SQL_MANAGEMENT_CONFIG
  3  WHERE PARAMETER_NAME = 'PLAN_RETENTION_WEEKS';

PARAMETER_NAME                 PARAMETER_
------------------------------ ----------
PLAN_RETENTION_WEEKS           105

Manually Evolve and Accept SQL PLAN BASELINES in Oracle 12c

这里将介绍如何使用命令行来evolve sql plan baselines。为了evolve一个特定的sql执行计划执行以下操作:
1.创建一个evolve任务
2.设置evolve任务参数
3.执行evolve任务
4.实现任务中给出的建议
5.显示任务执行的结果

下面将举例来说明,假设满足以下条件
.数据库没有启用自动evolve任务
.对下面的查询创建一个SQL Plan Baseline

SELECT /* q2_group_by */ prod_name, sum(quantity_sold)
FROM products p, sales s
WHERE p.prod_id = s.prod_id
AND p.prod_category_id =204
GROUP BY prod_name;

.想要创建两个索引来提高查询语句的性能,如果使用索引的性能比SQL Plan Baseline中的当前执行计划的性能好那么就evolve该执行计划

为了evolve一个特定的执行计划需要执行以下操作
1.执行初始化设置操作
清空共享池与缓冲区缓存

SQL> ALTER SYSTEM FLUSH SHARED_POOL;

System altered.

SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;

System altered.

启用自动捕获SQL Plan Baselines

SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=true;

System altered.

SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     TRUE
optimizer_use_sql_plan_baselines     boolean     TRUE

以sh用户登录到数据库,然后设置SQLPLUS的显示参数

[oracle@jytest1 ~]$ sqlplus sh/sh@jypdb

SQL*Plus: Release 12.2.0.1.0 Production on Thu Feb 14 23:30:09 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Last Successful login time: Thu Feb 14 2019 23:01:23 +08:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production


SQL> SET PAGES 10000 LINES 140
SQL> SET SERVEROUTPUT ON
SQL> COL SQL_TEXT FORMAT A20
SQL> COL SQL_HANDLE FORMAT A20
SQL> COL PLAN_NAME FORMAT A30
SQL> COL ORIGIN FORMAT A12
SQL> SET LONGC 60535
SQL> SET LONG 60535
SQL> SET ECHO ON

2.执行SQL语句,因此可以自动捕获它
执行下面的SQL语句

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

查询数据字典确认在SQL Plan Baseline中不存在执行计划,因为只有重复执行的SQL语句才会被捕获

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED,
  2  ACCEPTED, FIXED, AUTOPURGE
  3  FROM DBA_SQL_PLAN_BASELINES
  4  WHERE SQL_TEXT LIKE '%q1_group%';

no rows selected

再次执行SQL语句

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

3.查询数据字典来确保执行计划已经被加载到SQL Plan Baseline中了,下面的查询显示执行计划已经被接受,这意味着执行计划已经存储在SQL Plan Baselines中了。origin列显示为AUTO-CAPTURE,这意味着执行计划是被自动捕获的

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME,
  2  ORIGIN, ENABLED, ACCEPTED, FIXED
  3  FROM DBA_SQL_PLAN_BASELINES
  4  WHERE SQL_TEXT LIKE '%q1_group%';

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN       ENA ACC FIX
-------------------- -------------------- ------------------------------ ------------ --- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE YES YES NO
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

4.下面对SQL语句进行解析并验证优化器是否会使用SQL Plan Baseline中的执行计划

SQL> EXPLAIN PLAN FOR
  2  SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  3  FROM products p, sales s
  4  WHERE p.prod_id = s.prod_id
  5  AND p.prod_category_id =203
  6  GROUP BY prod_name;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(null, null, 'basic +note'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3535171836

------------------------------------------
| Id  | Operation             | Name     |
------------------------------------------
|   0 | SELECT STATEMENT      |          |
|   1 |  HASH GROUP BY        |          |
|   2 |   HASH JOIN           |          |
|   3 |    TABLE ACCESS FULL  | PRODUCTS |
|   4 |    PARTITION RANGE ALL|          |
|   5 |     TABLE ACCESS FULL | SALES    |
------------------------------------------

Note
-----
   - SQL plan baseline "SQL_PLAN_0gwbcfvzskcu242949306" used for this statement

16 rows selected.

从执行计划的Note部分可以看到SQL Plan Baseline已经应用到这个SQL语句了

5.创建两个索引用来提高上面SQL语句的性能

SQL> CREATE INDEX ind_prod_cat_name ON products(prod_category_id, prod_name, prod_id);

Index created.

SQL> CREATE INDEX ind_sales_prod_qty_sold ON sales(prod_id, quantity_sold);

Index created.

6.再次执行SQL语句,因为启用了自动捕获功能,所以新的执行计划会被加载到SQL Plan Baseline中

SQL> SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  2  FROM products p, sales s
  3  WHERE p.prod_id = s.prod_id
  4  AND p.prod_category_id =203
  5  GROUP BY prod_name;

PROD_NAME                                          SUM(QUANTITY_SOLD)
-------------------------------------------------- ------------------
Envoy External 6X CD-ROM                                        11526
Model SM26273 Black Ink Cartridge                               15910
PCMCIA modem/fax 28800 baud                                     19278
Multimedia speakers- 3" cones                                   10969
Internal 8X CD-ROM                                              11197
Deluxe Mouse                                                    11609
Model CD13272 Tricolor Ink Cartridge                            12321
Model NM500X High Yield Toner Cartridge                          6466
18" Flat Panel Graphics Monitor                                  4415
External 8X CD-ROM                                              13886
SIMM- 8MB PCMCIAII card                                         17544
PCMCIA modem/fax 19200 baud                                     20467
Envoy External 8X CD-ROM                                        14850
Envoy External Keyboard                                          2857
External 6X CD-ROM                                              11732
Model A3827H Black Image Cartridge                              17314
Internal 6X CD-ROM                                               8533
17" LCD w/built-in HDTV Tuner                                    4874
SIMM- 16MB PCMCIAII card                                        14191
Multimedia speakers- 5" cones                                   10419
Standard Mouse                                                   8714

21 rows selected.

7.查询数据字典来确保新的执行计划被加载到SQL Plan Baseline中了

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED
  2  FROM DBA_SQL_PLAN_BASELINES
  3  WHERE SQL_HANDLE IN ('SQL_07f16c76ff893342')
  4  ORDER BY SQL_HANDLE, ACCEPTED;

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN       ENA ACC
-------------------- -------------------- ------------------------------ ------------ --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu20135fd6c AUTO-CAPTURE YES NO
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

上面的查询结果显示新的执行计划是为被接受的。

8.再次解析SQL语句并验证优化器是不是使用原始没有索引的执行计划

SQL> EXPLAIN PLAN FOR
  2  SELECT /* q1_group_by */ prod_name, sum(quantity_sold)
  3  FROM products p, sales s
  4  WHERE p.prod_id = s.prod_id
  5  AND p.prod_category_id =203
  6  GROUP BY prod_name;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(null, null, 'basic +note'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3535171836

------------------------------------------
| Id  | Operation             | Name     |
------------------------------------------
|   0 | SELECT STATEMENT      |          |
|   1 |  HASH GROUP BY        |          |
|   2 |   HASH JOIN           |          |
|   3 |    TABLE ACCESS FULL  | PRODUCTS |
|   4 |    PARTITION RANGE ALL|          |
|   5 |     TABLE ACCESS FULL | SALES    |
------------------------------------------

Note
-----
   - SQL plan baseline "SQL_PLAN_0gwbcfvzskcu242949306" used for this statement

16 rows selected.

上面的Note部分指示优化器使用了原始的没有索引的执行计划

9.以管理员用户登录数据库,然后创建一个evolve任务它包含未被接受执行计划相关的所有SQL语句

[oracle@jytest1 ~]$ sqlplus sys/xxzx7817600@jypdb as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Thu Feb 14 23:48:51 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> VARIABLE cnt NUMBER
SQL> VARIABLE tk_name VARCHAR2(50)
SQL> VARIABLE exe_name VARCHAR2(50)
SQL> VARIABLE evol_out CLOB
SQL> EXECUTE :tk_name := DBMS_SPM.CREATE_EVOLVE_TASK(sql_handle => 'SQL_07f16c76ff893342',plan_name => 'SQL_PLAN_0gwbcfvzskcu20135fd6c');

PL/SQL procedure successfully completed.

SQL> SELECT :tk_name FROM DUAL;

:TK_NAME
--------------------------------------------------------------------------------------------------------------------------------
TASK_11



10.执行evolve任务
SQL>EXECUTE :exe_name :=DBMS_SPM.EXECUTE_EVOLVE_TASK(task_name=>:tk_name);
PL/SQL procedure successfully completed.

SQL>SELECT :exe_name FROM DUAL;
:EXE_NAME
---------------------------------------------------------------------------
EXEC_1

11.查看报告

EXECUTE :evol_out := DBMS_SPM.REPORT_EVOLVE_TASK( task_name=>:tk_name,
execution_name=>:exe_name );
SELECT :evol_out FROM DUAL;
GENERAL INFORMATION SECTION
--------------------------------------------------------------------------
Task Information:
---------------------------------------------
Task Name : TASK_11
Task Owner : SYS
Execution Name : EXEC_1
Execution Type       : SPM EVOLVE
Scope                : COMPREHENSIVE
Status               : COMPLETED
Started              : 02/15/2019 17:49:32
Finished             : 02/15/2019 17:49:35
Last Updated         : 02/15/2019 17:49:35
Global Time Limit    : 2147483646
Per-Plan Time Limit  : UNUSED
Number of Errors     : 0
---------------------------------------------------------------------------
SUMMARY SECTION
---------------------------------------------------------------------------
Number of plans processed : 1
Number of findings : 1
Number of recommendations : 1
Number of errors : 0
---------------------------------------------------------------------------
DETAILS SECTION
---------------------------------------------------------------------------
Object ID : 2
Test Plan Name : SQL_PLAN_0gwbcfvzskcu20135fd6c
Base Plan Name : SQL_PLAN_0gwbcfvzskcu242949306
SQL Handle : SQL_07f16c76ff893342
Parsing Schema : SH
Test Plan Creator : SH
SQL Text : SELECT /*q1_group_by*/ prod_name,
sum(quantity_sold)
FROM products p, sales s
WHERE p.prod_id=s.prod_id AND p.prod_category_id=203
GROUP BY prod_name
Execution Statistics:
-----------------------------
Base Plan Test Plan
---------------------------- ------------------------
Elapsed Time (s): .044336 .012649
CPU Time (s): .044003 .012445
Buffer Gets: 360 99
Optimizer Cost: 924 891
Disk Reads: 341 82
Direct Writes: 0 0
Rows Processed: 4 2
Executions: 5 9
FINDINGS SECTION
---------------------------------------------------------------------------
Findings (1):
-----------------------------
1. The plan was verified in 2.18 seconds. It passed the benefit criterion
because its verified performance was 2.01 times better than that of the
baseline plan.
Recommendation:
-----------------------------
Consider accepting the plan. Execute
dbms_spm.accept_sql_plan_baseline(task_name => 'TASK_11', object_id => 2,
task_owner => 'SYS');
EXPLAIN PLANS SECTION
---------------------------------------------------------------------------
Baseline Plan
-----------------------------
Plan Id : 1
Plan Hash Value : 1117033222
---------------------------------------------------------------------------
| Id| Operation               | Name     | Rows | Bytes   |Cost | Time    |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT        |          |   21 |     861 | 924 | 00:00:12|
| 1 |   HASH GROUP BY         |          |   21 |     861 | 924 | 00:00:12|
| *2|    HASH JOIN            |          |267996|10987836 | 742 | 00:00:09|
| *3|     TABLE ACCESS FULL   | PRODUCTS |   21 |     714 |   2 | 00:00:01|
| 4 |     PARTITION RANGE ALL |          |918843| 6431901 | 662 | 00:00:08|
| 5 |      TABLE ACCESS FULL  | SALES    |918843| 6431901 | 662 | 00:00:08|
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access("P"."PROD_ID"="S"."PROD_ID")
* 3 - filter("P"."PROD_CATEGORY_ID"=203)
Test Plan
-----------------------------
Plan Id : 2
Plan Hash Value : 20315500
---------------------------------------------------------------------------
|Id| Operation           | Name             | Rows | Bytes  | Cost| Time   |
---------------------------------------------------------------------------
| 0|SELECT STATEMENT     |                  |    21|     861|  891|00:00:11|
| 1| SORT GROUP BY NOSORT|                  |    21|     861|  891|00:00:11|
| 2|  NESTED LOOPS       |                  |267996|10987836|  891|00:00:11|
|*3|   INDEX RANGE SCAN  |IND_PROD_CAT_NAME |    21|     714|    1|00:00:01|
|*4|   INDEX RANGE SCAN  |IND_SALES_PROD_QTY| 12762|   89334|   42|00:00:01|
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("P"."PROD_CATEGORY_ID"=203)
* 4 - access("P"."PROD_ID"="S"."PROD_ID")

报告显示使用两个索引的执行计划比原始执行计划性能更好

12.实现evolve任务所给出的建议

SQL>EXECUTE :cnt := DBMS_SPM.IMPLEMENT_EVOLVE_TASK( task_name=>:tk_name,execution_name=>:exe_name );
PL/SQL procedure successfully completed.

13.查询数据字典来确保新的执行计划已经是接受状态

SQL> SELECT SQL_HANDLE, SQL_TEXT, PLAN_NAME, ORIGIN, ENABLED, ACCEPTED
  2  FROM DBA_SQL_PLAN_BASELINES
  3  WHERE SQL_HANDLE IN ('SQL_07f16c76ff893342')
  4  ORDER BY SQL_HANDLE, ACCEPTED;

SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu242949306 AUTO-CAPTURE         YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name


SQL_HANDLE           SQL_TEXT             PLAN_NAME                      ORIGIN               ENA ACC
-------------------- -------------------- ------------------------------ -------------------- --- ---
SQL_07f16c76ff893342 SELECT /* q1_group_b SQL_PLAN_0gwbcfvzskcu2ae9b4305 AUTO-CAPTURE         YES YES
                     y */ prod_name, sum(
                     quantity_sold)
                     FROM products p, sal
                     es s
                     WHERE p.prod_id = s.
                     prod_id
                     AND p.prod_category_
                     id =203
                     GROUP BY prod_name

14.执行清除操作

SQL> VARIABLE cnt NUMBER
SQL> EXEC :cnt := DBMS_SPM.DROP_SQL_PLAN_BASELINE('SQL_07f16c76ff893342');

PL/SQL procedure successfully completed.


SQL> DELETE FROM SQLLOG$;

13 rows deleted.

SQL> commit;

Commit complete.


SQL> DROP INDEX IND_SALES_PROD_QTY_SOLD;
Index dropped.



SQL> DROP INDEX IND_PROD_CAT_NAME;

Index dropped.

Disable the Evolve Job SYS_AUTO_SPM_EVOLVE_TASK in Oracle 12c

为了禁用自动SPM EVOLVE TASK需要执行以下操作
1. 查看自动SPM Evolve Task是否启用

SQL> COL CLIENT_NAME FORMAT a20
SQL>
SQL> SELECT CLIENT_NAME, STATUS
  2  FROM   DBA_AUTOTASK_CLIENT
  3  WHERE  CLIENT_NAME = 'sql tuning advisor';

CLIENT_NAME          STATUS
-------------------- --------
sql tuning advisor   ENABLED

2.禁用自动SPM Evolve Task

SQL> BEGIN
  2    DBMS_AUTO_TASK_ADMIN.DISABLE (
  3      client_name => 'sql tuning advisor'
  4  ,   operation   => NULL
  5  ,   window_name => NULL
  6  );
  7  END;
  8  /

PL/SQL procedure successfully completed.

SQL> SELECT CLIENT_NAME, STATUS
  2  FROM   DBA_AUTOTASK_CLIENT
  3  WHERE  CLIENT_NAME = 'sql tuning advisor';

CLIENT_NAME          STATUS
-------------------- --------
sql tuning advisor   DISABLED

3. 查看SPM Evolve Task的参数设置

SQL> SELECT parameter_name, parameter_value
  2  FROM dba_advisor_parameters
  3  WHERE task_name = 'SYS_AUTO_SPM_EVOLVE_TASK'
  4  AND parameter_value != 'UNUSED'
  5  ORDER BY parameter_name;

PARAMETER_NAME                                                                   PARAMETER_VALUE
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ACCEPT_PLANS                                                                     true
ALTERNATE_PLAN_BASELINE                                                          EXISTING
ALTERNATE_PLAN_LIMIT                                                             0
ALTERNATE_PLAN_SOURCE                                                            CURSOR_CACHE+AUTOMATIC_WORKLOAD_REPOSITORY
DAYS_TO_EXPIRE                                                                   UNLIMITED
DEFAULT_EXECUTION_TYPE                                                           SPM EVOLVE
EXECUTION_DAYS_TO_EXPIRE                                                         30
JOURNALING                                                                       INFORMATION
MODE                                                                             COMPREHENSIVE
TARGET_OBJECTS                                                                   1
TIME_LIMIT                                                                       3600
_SPM_VERIFY                                                                      TRUE

12 rows selected

4. 关闭Automatic Evolving of Baselines

SQL> BEGIN
  2  DBMS_SPM.set_evolve_task_parameter(
  3  task_name => 'SYS_AUTO_SPM_EVOLVE_TASK',
  4  parameter => 'ACCEPT_PLANS',
  5  value => 'FALSE');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL> SELECT parameter_name, parameter_value
  2  FROM dba_advisor_parameters
  3  WHERE task_name = 'SYS_AUTO_SPM_EVOLVE_TASK'
  4  AND parameter_value != 'UNUSED'
  5  ORDER BY parameter_name;

PARAMETER_NAME                                                                   PARAMETER_VALUE
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ACCEPT_PLANS                                                                     FALSE
ALTERNATE_PLAN_BASELINE                                                          EXISTING
ALTERNATE_PLAN_LIMIT                                                             0
ALTERNATE_PLAN_SOURCE                                                            CURSOR_CACHE+AUTOMATIC_WORKLOAD_REPOSITORY
DAYS_TO_EXPIRE                                                                   UNLIMITED
DEFAULT_EXECUTION_TYPE                                                           SPM EVOLVE
EXECUTION_DAYS_TO_EXPIRE                                                         30
JOURNALING                                                                       INFORMATION
MODE                                                                             COMPREHENSIVE
TARGET_OBJECTS                                                                   1
TIME_LIMIT                                                                       3600
_SPM_VERIFY                                                                      TRUE

12 rows selected

5. 启用Automatic Evolving of Baselines

SQL> BEGIN
  2  DBMS_SPM.set_evolve_task_parameter(
  3  task_name => 'SYS_AUTO_SPM_EVOLVE_TASK',
  4  parameter => 'ACCEPT_PLANS',
  5  value => 'TRUE');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL> SELECT parameter_name, parameter_value
  2  FROM dba_advisor_parameters
  3  WHERE task_name = 'SYS_AUTO_SPM_EVOLVE_TASK'
  4  AND parameter_value != 'UNUSED'
  5  ORDER BY parameter_name;

PARAMETER_NAME                                                                   PARAMETER_VALUE
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ACCEPT_PLANS                                                                     true
ALTERNATE_PLAN_BASELINE                                                          EXISTING
ALTERNATE_PLAN_LIMIT                                                             0
ALTERNATE_PLAN_SOURCE                                                            CURSOR_CACHE+AUTOMATIC_WORKLOAD_REPOSITORY
DAYS_TO_EXPIRE                                                                   UNLIMITED
DEFAULT_EXECUTION_TYPE                                                           SPM EVOLVE
EXECUTION_DAYS_TO_EXPIRE                                                         30
JOURNALING                                                                       INFORMATION
MODE                                                                             COMPREHENSIVE
TARGET_OBJECTS                                                                   1
TIME_LIMIT                                                                       3600
_SPM_VERIFY                                                                      TRUE

12 rows selected

Oracle 12.2 ORA-01113 ORA-01110 recover after normal shutdown

Oracle Linux 7.1数据库为Oracle 12.2.0.1 RAC,数据库启用了归档,在手动关闭数据库后启动数据库时提示PDB库有数据文件需要进行介质恢复

[grid@jytest1 ~]$ srvctl stop database -db jy
[grid@jytest1 ~]$ crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.ASMNET1LSNR_ASM.lsnr
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.CRS.dg
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.DATA.dg
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.FRA.dg
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.LISTENER.lsnr
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.TEST.dg
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.chad
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.net1.network
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.ons
               ONLINE  ONLINE       jytest1                  STABLE
               ONLINE  ONLINE       jytest2                  STABLE
ora.proxy_advm
               OFFLINE OFFLINE      jytest1                  STABLE
               OFFLINE OFFLINE      jytest2                  STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       jytest1                  STABLE
ora.LISTENER_SCAN2.lsnr
      1        ONLINE  ONLINE       jytest2                  STABLE
ora.LISTENER_SCAN3.lsnr
      1        ONLINE  ONLINE       jytest2                  STABLE
ora.MGMTLSNR
      1        ONLINE  ONLINE       jytest2                  169.254.237.250 88.8
                                                             8.88.2,STABLE
ora.asm
      1        ONLINE  ONLINE       jytest1                  Started,STABLE
      2        ONLINE  ONLINE       jytest2                  STABLE
      3        ONLINE  OFFLINE                               STABLE

ora.cvu
      1        ONLINE  ONLINE       jytest2                  STABLE
ora.jy.db
      1        OFFLINE OFFLINE                               Instance Shutdown,ST
                                                             ABLE
      2        OFFLINE OFFLINE                               Instance Shutdown,ST
                                                             ABLE
ora.jy.jy_srv.svc
      1        OFFLINE OFFLINE                               STABLE
ora.jytest1.vip
      1        ONLINE  ONLINE       jytest1                  STABLE
ora.jytest2.vip
      1        ONLINE  ONLINE       jytest2                  STABLE
ora.mgmtdb
      1        ONLINE  ONLINE       jytest2                  Open,STABLE
ora.qosmserver
      1        ONLINE  ONLINE       jytest1                  STABLE
ora.scan1.vip
      1        ONLINE  ONLINE       jytest1                  STABLE
ora.scan2.vip
      1        ONLINE  ONLINE       jytest2                  STABLE
ora.scan3.vip
      1        ONLINE  ONLINE       jytest2                  STABLE
--------------------------------------------------------------------------------

提示PDB的数据文件需要进行介质恢复,文件号是38

[grid@jytest1 ~]$ srvctl start database -db jy
PRCR-1079 : Failed to start resource ora.jy.db
CRS-5017: The resource action "ora.jy.db start" encountered the following error: 
ORA-01113: file 38 needs media recovery
ORA-01110: data file 38: '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649'
. For details refer to "(:CLSN00107:)" in "/u01/app/grid/diag/crs/jytest2/crs/trace/crsd_oraagent_oracle.trc".

CRS-2674: Start of 'ora.jy.db' on 'jytest2' failed
CRS-5017: The resource action "ora.jy.db start" encountered the following error: 
ORA-01113: file 38 needs media recovery
ORA-01110: data file 38: '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649'
. For details refer to "(:CLSN00107:)" in "/u01/app/grid/diag/crs/jytest1/crs/trace/crsd_oraagent_oracle.trc".

CRS-2674: Start of 'ora.jy.db' on 'jytest1' failed
CRS-2632: There are no more servers to try to place resource 'ora.jy.db' on that would satisfy its placement policy

对38号文件执行介质恢复

[oracle@jytest1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Wed Feb 13 17:47:55 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area 2147483648 bytes
Fixed Size                  8794848 bytes
Variable Size            1610616096 bytes
Database Buffers          520093696 bytes
Redo Buffers                7979008 bytes
Database mounted.
ORA-01113: file 38 needs media recovery
ORA-01110: data file 38:
'+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649'


SQL> recover datafile 38;
Media recovery complete.

在对38号文件进行介质恢复后打开CDB时提示39号文件也需要进行介质恢复

SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01113: file 39 needs media recovery
ORA-01110: data file 39:
'+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/sysaux.316.962209649'

如是执行recover database命令来对CDB进行介质恢复并打开CDB

SQL> recover database;
Media recovery complete.
SQL> alter database open;

Database altered.

在打开JYPDB时提示PDB的45号文件需要进行介质恢复

SQL> alter pluggable database jypdb open;
alter pluggable database jypdb open
*
ERROR at line 1:
ORA-01113: file 45 needs media recovery
ORA-01110: data file 45:
'+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783'

如是对45号文件进行介质恢复,虽然介质恢复成功但在打开jypdb时仍然提示需要进行介质恢复

SQL>  recover datafile 45;
Media recovery complete.

SQL> alter pluggable database jypdb open;
alter pluggable database jypdb open
*
ERROR at line 1:
ORA-01113: file 45 needs media recovery
ORA-01110: data file 45:
'+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783'

如是查询数据文件检查点SCN与数据文件头SCN,发现44与45号文件的数据文件检查点SCN与数据文件头SCN号不一致并且数据文件检查点SCN比数据文件头SCN号大,因此需要进行日志文件来进行恢复。但在执行recover datafile命令成功后,打开JYPDB时仍然提示需要进行介质恢复。

SQL> select FILE#, CHECKPOINT_CHANGE#,LAST_CHANGE# from v$datafile;

     FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
         1          176117998
         3          176117998
         4          176117998
         5            1449535      1449535
         6            1449535      1449535
         7          176117998
         8            1449535      1449535
         9          176117998
        38          176098593    176098593
        39          176098593    176098593
        40          176098593    176098593

     FILE# CHECKPOINT_CHANGE# LAST_CHANGE#
---------- ------------------ ------------
        41          176098593    176098593
        42          176098593    176098593
        43          176098593    176098593
        44          176098593    175898322
        45          176098593    175898322
        46           21664676     21664676
        47           21664676     21664676
        48           21664676     21664676
        49           21664676     21664676
        50           21664676     21664676
        51           21664676     21664676

22 rows selected.

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1          176117998
         3          176117998
         4          176117998
         5            1449535
         6            1449535
         7          176117998
         8            1449535
         9          176117998
        38          176098593
        39          176098593
        40          176098593

     FILE# CHECKPOINT_CHANGE#
---------- ------------------
        41          176098593
        42          176098593
        43          176098593
        44          175898322
        45          175898322
        46           21664676
        47           21664676
        48           21664676
        49           21664676
        50           21664676
        51           21664676

22 rows selected.

如是打算重建控制文件再执行介质恢复,下面先备份控制文件到跟踪文件,在跟踪文件中有重建控制文件的相关命令

SQL> alter database backup controlfile to trace as '/tmp/ctl.txt';

Database altered.

关闭RAC数据库

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

将RAC数据库启动到nomount状态

SQL> STARTUP NOMOUNT
ORACLE instance started.

Total System Global Area 2147483648 bytes
Fixed Size                  8794848 bytes
Variable Size            1610616096 bytes
Database Buffers          520093696 bytes
Redo Buffers                7979008 bytes

重建控制文件,提示数据库不是排他模式,也就是说在RAC环境不能重建控制文件

SQL> CREATE CONTROLFILE REUSE DATABASE "JY" NORESETLOGS  ARCHIVELOG
  2      MAXLOGFILES 192
  3      MAXLOGMEMBERS 3
  4      MAXDATAFILES 1024
  5      MAXINSTANCES 32
  6      MAXLOGHISTORY 292
  7  LOGFILE
  8    GROUP 1 '+DATA/JY/ONLINELOG/group_1.261.961976319'  SIZE 200M BLOCKSIZE 512,
  9    GROUP 2 '+DATA/JY/ONLINELOG/group_2.302.961976321'  SIZE 200M BLOCKSIZE 512,
 10    GROUP 3 '+DATA/JY/ONLINELOG/group_3.263.961976697'  SIZE 200M BLOCKSIZE 512,
 11    GROUP 4 '+DATA/JY/ONLINELOG/group_4.262.961976705'  SIZE 200M BLOCKSIZE 512,
 12    GROUP 6 (
 13      '+DATA/JY/ONLINELOG/group_6.280.972435899',
 14      '+FRA/JY/ONLINELOG/group_6.354.972435909'
 15    ) SIZE 200M BLOCKSIZE 512
 16  -- STANDBY LOGFILE
 17  DATAFILE
 18    '+DATA/JY/DATAFILE/system.317.962209603',
 19    '+DATA/JY/DATAFILE/sysaux.298.962209605',
 20    '+DATA/JY/DATAFILE/undotbs1.277.962209605',
 21    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/system.256.962209675',
 22    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/sysaux.270.962209675',
 23    '+DATA/JY/DATAFILE/users.301.962209605',
 24    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/undotbs1.296.962209675',
 25    '+DATA/JY/DATAFILE/undotbs2.312.962209605',
 26    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649',
 27    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/sysaux.316.962209649',
 28    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undotbs1.264.962209649',
 29    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undo_2.268.962209649',
 30    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/users.278.962209649',
 31    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/test.275.962210609',
 32    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/tts.257.966380353',
 33    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783',
 34    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/system.260.962469409',
 35    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/sysaux.259.962469409',
 36    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undotbs1.265.962469409',
 37    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undo_2.266.962469409',
 38    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/users.267.962469409',
 39    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/test.269.962469409'
 40  CHARACTER SET ZHS16GBK
 41  ;
CREATE CONTROLFILE REUSE DATABASE "JY" NORESETLOGS  ARCHIVELOG
*
ERROR at line 1:
ORA-01503: CREATE CONTROLFILE failed
ORA-12720: operation requires database is in EXCLUSIVE mode

修改数据库为排他模式

SQL> show parameter cluster

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cdb_cluster                          boolean     FALSE
cdb_cluster_name                     string      jy
cluster_database                     boolean     TRUE
cluster_database_instances           integer     2
cluster_interconnects                string

SQL> alter system set cluster_database=false scope=spfile sid='*';

System altered.

重启数据库到nomount状态

SQL> shtudown immediate
SP2-0734: unknown command beginning "shtudown i..." - rest of line ignored.
SQL> shutdown immediate
ORA-01507: database not mounted


ORACLE instance shut down.

SQL> STARTUP NOMOUNT
ORACLE instance started.

Total System Global Area 2147483648 bytes
Fixed Size                  8794848 bytes
Variable Size            1459621152 bytes
Database Buffers          671088640 bytes
Redo Buffers                7979008 bytes

重建控制文件

SQL> CREATE CONTROLFILE REUSE DATABASE "JY" NORESETLOGS  ARCHIVELOG
  2      MAXLOGFILES 192
  3      MAXLOGMEMBERS 3
  4      MAXDATAFILES 1024
  5      MAXINSTANCES 32
  6      MAXLOGHISTORY 292
  7  LOGFILE
  8    GROUP 1 '+DATA/JY/ONLINELOG/group_1.261.961976319'  SIZE 200M BLOCKSIZE 512,
  9    GROUP 2 '+DATA/JY/ONLINELOG/group_2.302.961976321'  SIZE 200M BLOCKSIZE 512,
 10    GROUP 3 '+DATA/JY/ONLINELOG/group_3.263.961976697'  SIZE 200M BLOCKSIZE 512,
 11    GROUP 4 '+DATA/JY/ONLINELOG/group_4.262.961976705'  SIZE 200M BLOCKSIZE 512,
 12    GROUP 6 (
 13      '+DATA/JY/ONLINELOG/group_6.280.972435899',
 14      '+FRA/JY/ONLINELOG/group_6.354.972435909'
 15    ) SIZE 200M BLOCKSIZE 512
 16  -- STANDBY LOGFILE
 17  DATAFILE
 18    '+DATA/JY/DATAFILE/system.317.962209603',
 19    '+DATA/JY/DATAFILE/sysaux.298.962209605',
 20    '+DATA/JY/DATAFILE/undotbs1.277.962209605',
 21    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/system.256.962209675',
 22    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/sysaux.270.962209675',
 23    '+DATA/JY/DATAFILE/users.301.962209605',
 24    '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/undotbs1.296.962209675',
 25    '+DATA/JY/DATAFILE/undotbs2.312.962209605',
 26    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649',
 27    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/sysaux.316.962209649',
 28    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undotbs1.264.962209649',
 29    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undo_2.268.962209649',
 30    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/users.278.962209649',
 31    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/test.275.962210609',
 32    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/tts.257.966380353',
 33    '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783',
 34    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/system.260.962469409',
 35    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/sysaux.259.962469409',
 36    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undotbs1.265.962469409',
 37    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undo_2.266.962469409',
 38    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/users.267.962469409',
 39    '+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/test.269.962469409'
 40  CHARACTER SET ZHS16GBK
 41  ;

Control file created.

如是查询数据文件检查点SCN与数据文件头SCN,现在44与45号文件的数据文件检查点SCN与数据文件头SCN号仍然不一致并且数据文件检查点SCN比数据文件头SCN号大

SQL> col name for a100
SQL> select name,checkpoint_change# from v$datafile_header;

NAME                                                                                                 CHECKPOINT_CHANGE#
---------------------------------------------------------------------------------------------------- ------------------
+DATA/JY/DATAFILE/system.317.962209603                                                                        176144167
+DATA/JY/DATAFILE/sysaux.298.962209605                                                                        176144167
+DATA/JY/DATAFILE/undotbs1.277.962209605                                                                      176144167
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/system.256.962209675                                         1449535
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/sysaux.270.962209675                                         1449535
+DATA/JY/DATAFILE/users.301.962209605                                                                         176144167
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/undotbs1.296.962209675                                       1449535
+DATA/JY/DATAFILE/undotbs2.312.962209605                                                                      176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649                                       176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/sysaux.316.962209649                                       176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undotbs1.264.962209649                                     176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undo_2.268.962209649                                       176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/users.278.962209649                                        176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/test.275.962210609                                         176098593
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/tts.257.966380353                                          175898322
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783                                           175898322
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/system.260.962469409                                        21664676
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/sysaux.259.962469409                                        21664676
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undotbs1.265.962469409                                      21664676
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undo_2.266.962469409                                        21664676
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/users.267.962469409                                         21664676
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/test.269.962469409                                          21664676

22 rows selected.

SQL> select name,checkpoint_change# from v$datafile;

NAME                                                                                                 CHECKPOINT_CHANGE#
---------------------------------------------------------------------------------------------------- ------------------
+DATA/JY/DATAFILE/system.317.962209603                                                                        176144167
+DATA/JY/DATAFILE/sysaux.298.962209605                                                                        176144167
+DATA/JY/DATAFILE/undotbs1.277.962209605                                                                      176144167
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/system.256.962209675                                       176144167
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/sysaux.270.962209675                                       176144167
+DATA/JY/DATAFILE/users.301.962209605                                                                         176144167
+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/DATAFILE/undotbs1.296.962209675                                     176144167
+DATA/JY/DATAFILE/undotbs2.312.962209605                                                                      176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/system.271.962209649                                       176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/sysaux.316.962209649                                       176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undotbs1.264.962209649                                     176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/undo_2.268.962209649                                       176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/users.278.962209649                                        176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/test.275.962210609                                         176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/tts.257.966380353                                          176144167
+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/DATAFILE/cs.294.966380783                                           176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/system.260.962469409                                       176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/sysaux.259.962469409                                       176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undotbs1.265.962469409                                     176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/undo_2.266.962469409                                       176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/users.267.962469409                                        176144167
+DATA/JY/600D6F56DEB669CCE053AB828A0AAB7E/DATAFILE/test.269.962469409                                         176144167

22 rows selected.

对CDB执行介质恢复操作,根据提示输入相关的归档日志文件名来进行恢复并将CDB成功打开

SQL> recover database
ORA-00279: change 175898322 generated at  needed for thread 2


Specify log: {=suggested | filename | AUTO | CANCEL}
+TEST/JY/ARCHIVELOG/2019_02_13/thread_2_seq_1073.422.1000144183
ORA-00279: change 176098395 generated at 02/13/2019 17:49:43 needed for thread 2
ORA-00289: suggestion : +TEST/arch/2_1074_961976319.dbf
ORA-00280: change 176098395 for thread 2 is in sequence #1074


Specify log: {=suggested | filename | AUTO | CANCEL}
 +TEST/JY/ARCHIVELOG/2019_02_13/thread_2_seq_1074.382.1000144185
ORA-00279: change 176098399 generated at 02/13/2019 17:49:45 needed for thread 2
ORA-00289: suggestion : +TEST/arch/2_1075_961976319.dbf
ORA-00280: change 176098399 for thread 2 is in sequence #1075


Specify log: {=suggested | filename | AUTO | CANCEL}
+TEST/arch/2_1075_961976319.dbf
ORA-00279: change 176098399 generated at 02/13/2019 17:49:45 needed for thread 1
ORA-00289: suggestion : +TEST/arch/1_1182_961976319.dbf
ORA-00280: change 176098399 for thread 1 is in sequence #1182


Specify log: {=suggested | filename | AUTO | CANCEL}
 +TEST/arch/1_1182_961976319.dbf
ORA-00279: change 176098401 generated at 02/13/2019 17:49:45 needed for thread 2
ORA-00289: suggestion : +TEST/arch/2_1076_961976319.dbf
ORA-00280: change 176098401 for thread 2 is in sequence #1076


Specify log: {=suggested | filename | AUTO | CANCEL}
 +TEST/arch/2_1076_961976319.dbf
ORA-00288: to continue recovery type ALTER DATABASE RECOVER CONTINUE
ORA-00278: log file '+TEST/arch/2_1076_961976319.dbf' no longer needed for this recovery


ORA-00279: change 176098489 generated at 02/13/2019 17:49:50 needed for thread 1
ORA-00289: suggestion : +TEST/arch/1_1183_961976319.dbf
ORA-00280: change 176098489 for thread 1 is in sequence #1183


Specify log: {=suggested | filename | AUTO | CANCEL}
+TEST/arch/1_1183_961976319.dbf
Log applied.
Media recovery complete.
SQL> alter database open;

Database altered.

将PDB数据库打开

SQL> ALTER PLUGGABLE DATABASE ALL OPEN;

Pluggable database altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 JYPDB                          READ WRITE NO

根据备份控制文件到跟踪文件重建控制文件的命令来添加临时表空间的相关文件

SQL> ALTER TABLESPACE TEMP ADD TEMPFILE '+DATA/JY/TEMPFILE/temp.299.961976339';

Tablespace altered.

SQL> ALTER SESSION SET CONTAINER = PDB$SEED;

Session altered.

SQL> ALTER TABLESPACE TEMP ADD TEMPFILE '+DATA/JY/5F9AA264B21F3ED9E053AB828A0A6088/TEMPFILE/temp.297.962209865'  SIZE 67108864  REUSE AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;

Tablespace altered.

SQL> ALTER SESSION SET CONTAINER = JYPDB;

Session altered.

SQL> ALTER TABLESPACE TEMP ADD TEMPFILE '+DATA/JY/5F9AC6865E87549FE053AB828A0ADE94/TEMPFILE/temp.276.967852391' REUSE;

Tablespace altered.

将数据库设置为集群模式并关闭数据库

SQL> alter system set cluster_database=true scope=spfile sid='*';

System altered.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

使用集群命令来启动数据库

[grid@jytest1 ~]$ srvctl start database -db jy

将JYPDB以读写方式打开

[oracle@jytest1 ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Wed Feb 13 22:30:53 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 JYPDB                          MOUNTED
SQL> alter pluggable database jypdb open;

Pluggable database altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 JYPDB                          READ WRITE NO


[oracle@jytest2 ~]$ sqlplus / as sysdba

SQL*Plus: Release 12.2.0.1.0 Production on Wed Feb 13 22:31:17 2019

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 JYPDB                          MOUNTED
SQL> alter pluggable database jypdb open;

Pluggable database altered.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 JYPDB                          READ WRITE NO

到此数据库的恢复操作就完成了

Oracle 12.2 How to Generate AWRs in Active Data Guard Standby Databases

从Oralce 12.2开始, 可以对Active Data Guard(ADG) standby database捕获AWR数据。这个功能可以对ADG备库的性能问题执行分析。在下面的例子中主库与备库都是两节点的RAC(db_name=cs)。主库(db_unique_name=cs),备库(db_unique_name=cs_dg)分别运行在cs1,cs2与jytest1,jytest2节点上。

1对备库确认数据库的open mode与database role

SQL> select inst_id, open_mode, database_role from gv$database order by 1;

   INST_ID OPEN_MODE            DATABASE_ROLE
---------- -------------------- ----------------
         1 READ ONLY WITH APPLY PHYSICAL STANDBY
         2 READ ONLY WITH APPLY PHYSICAL STANDBY

2.在主库中对sys$umf用户解锁并设置密码,因为sys$umf用户默认是被锁定的。sys$umf用户是缺省的数据库用户它有访问系统级别远程管理框架(RMF)视图与表的所有权限。在RMF中所有AWR相关的操作只能通过sys$umf用户来执行。

SQL> alter user sys$umf account unlock identified by xxzx7817600;

User altered.

3.创建两个dblink,一个是从主库到备库(cs_to_cs_dg),另一个是从备库到主库(cs_dg_to_cs)。但因为ADG库是只读的,所以创建dblink的操作都需要在主库运行

SQL> create database link cs_to_cs_dg connect to sys$umf identified by xxzx7817600 using 'cs_dg';

Database link created.

SQL> create database link cs_dg_to_cs connect to sys$umf identified by xxzx7817600 using 'cs';

Database link created.

4.需要将数据库节点配置到拓朴(topology)结构中,在拓朴结构中的每个数据库节点必须被指定一个唯一名(缺省值为db_unique_name),在这个例子中主库为cs,备库为cs_dg,在主库中执行以下命令

SQL> exec dbms_umf.configure_node ('cs');

PL/SQL procedure successfully completed.

5.在备库中执行以下命令,通过备库到主库的链路名来进行注册

SQL> exec dbms_umf.configure_node ('cs_dg','CS_DG_TO_CS');

PL/SQL procedure successfully completed.

6.创建RMF拓朴,在主库中执行以下命令

SQL> exec dbms_umf.create_topology ('topology_1');

PL/SQL procedure successfully completed.

7.执行以下语句来对上面的操作进行验证

SQL> set line 132
SQL> col topology_name format a15
SQL> col node_name format a15
SQL> select * from dba_umf_topology;

TOPOLOGY_NAME    TARGET_ID TOPOLOGY_VERSION TOPOLOGY
--------------- ---------- ---------------- --------
topology_1      1789571709                1 ACTIVE

SQL> select * from dba_umf_registration;

TOPOLOGY_NAME   NODE_NAME          NODE_ID  NODE_TYPE AS_SO AS_CA STATE
--------------- --------------- ---------- ---------- ----- ----- --------------------
topology_1      cs              1789571709          0 FALSE FALSE OK

8.向拓朴中注册备库,在主库中执行下面的命令

SQL> exec dbms_umf.register_node ('topology_1', 'cs_dg', 'CS_TO_CS_DG', 'CS_DG_TO_CS', 'FALSE', 'FALSE');

PL/SQL procedure successfully completed.

9.在主库上执行下面的操作把拓扑的ADG库cs_dg的AWR service开启:

SQL> exec dbms_workload_repository.register_remote_database(node_name=>'cs_dg');

PL/SQL procedure successfully completed.

如果遇到“ORA-15766: already registered in an RMF topology” 那么要先执行DBMS_UMF.unregister_node清除注册的节点然而再次执行DBMS_UMF.register_node来注册节点

如果遇到”ORA-13519: Database id (1730117407) exists in the workload repository”那么要先执行DBMS_WORKLOAD_REPOSITORY.unregister_remote_database清除远程数据库然后再次执行
DBMS_WORKLOAD_REPOSITORY.register_remote_database注册远程数据库。

10.配置ADG的AWR功能就做完了,可以检查相关视图来验证这个拓扑配置

SQL> set line 132
SQL> col topology_name format a15
SQL> col node_name format a15
SQL> select * from dba_umf_topology;

TOPOLOGY_NAME    TARGET_ID TOPOLOGY_VERSION TOPOLOGY
--------------- ---------- ---------------- --------
topology_1      1789571709                4 ACTIVE

SQL> select * from dba_umf_registration;

TOPOLOGY_NAME   NODE_NAME          NODE_ID  NODE_TYPE AS_SO AS_CA STATE
--------------- --------------- ---------- ---------- ----- ----- --------------------
topology_1      cs              1789571709          0 FALSE FALSE OK
topology_1      cs_dg           2145432700          0 FALSE FALSE OK

SQL> select * from dba_umf_link;

TOPOLOGY_NAME   FROM_NODE_ID TO_NODE_ID LINK_NAME
--------------- ------------ ---------- ----------------------------------------
topology_1        2145432700 1789571709 CS_DG_TO_CS
topology_1        1789571709 2145432700 CS_TO_CS_DG

SQL> select * from dba_umf_service;

TOPOLOGY_NAME      NODE_ID SERVICE
--------------- ---------- -------
topology_1      2145432700 AWR

11.这时候每当默认生成AWR snapshot时,主库与ADG库会同时生成。如果要手工生成ADG的AWR快照,可以在主库中执行下面的命令(参数值为ADG库的node_id或node_name)

SQL> exec dbms_workload_repository.create_remote_snapshot(2145432700);

PL/SQL procedure successfully completed.

SQL> exec dbms_workload_repository.create_remote_snapshot('cs_dg');

PL/SQL procedure successfully completed.

至少要执行两次命令来得到快照的begin_snap和end_snap。如果遇到 “ORA-13516: AWR Operation failed:Remote source not registered for AWR” 那么需要对主库执行alter system switch logfile命令
再切换日志文件两到三次。

12.如果要生成ADG库的AWR report,可以执行下面的操作:

SQL> @$ORACLE_HOME/rdbms/admin/awrrpti.sql

Specify the Report Type
~~~~~~~~~~~~~~~~~~~~~~~
AWR reports can be generated in the following formats.  Please enter the
name of the format at the prompt. Default value is 'html'.

   'html'          HTML format (default)
   'text'          Text format
   'active-html'   Includes Performance Hub active report

Enter value for report_type: html



Type Specified: html





Instances in this Workload Repository schema
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  DB Id      Inst Num   DB Name      Instance     Host
------------ ---------- ---------    ----------   ------
  1386528187     1      CS           cs1          cs1.jy.net
  1386528187     2      CS           cs2          cs2.jy.net
  2145432700     1      CS           cs1          jytest1.jydb
  2145432700     2      CS           cs2          jytest2.jydb

Enter value for dbid: 2145432700 这里需要指定备库的dbid
Using 2145432700 for database Id
Enter value for inst_num: 2  这里指定备库的实例ID
Using 2 for instance number


Specify the number of days of snapshots to choose from
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Entering the number of days (n) will result in the most recent
(n) days of snapshots being listed.  Pressing  without
specifying a number lists all completed snapshots.


Enter value for num_days: 1

Listing the last day's Completed Snapshots
Instance     DB Name      Snap Id       Snap Started    Snap Level
------------ ------------ ---------- ------------------ ----------

cs2          CS                   1  24 Jan 2019 23:50    1
                                  2  24 Jan 2019 23:51    1


Specify the Begin and End Snapshot Ids
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enter value for begin_snap: 1
Begin Snapshot Id specified: 1

Enter value for end_snap: 2
End   Snapshot Id specified: 2



Specify the Report Name
~~~~~~~~~~~~~~~~~~~~~~~
The default report file name is awrrpt_2_1_2.html.  To use this name,
press  to continue, otherwise enter an alternative.

Enter value for report_name: /home/oracle/cs_dg_1_2.html

Using the report name /home/oracle/cs_dg_1_2.html

下面是一个ADG库的AWR report的例子,可以看到数据库的Role为PHYSICAL STANDBY。

Oracle 12.2在Active Dataguard上引入AWR功能,可以让Active dataguard的数据库性能诊断更加容易。

Oracle 12.2 使用Database Link优化Standby Database Workload

从Oracle 12.2开始,可以通过在database_link_to参数来指定一个数据库链路来优化备库workload。由于安全原因,Oracle建议使用私有数据库链路。这个链路必须属于sys用户并且能让有权限的用户来访问。Oracle数据库包含一个缺省的权限用户名为SYS$UMF。

在主库中使用sys用户创建表t1与配置sys$umf用户,这个用户默认是被锁定的,所以需要先解锁这个用户并设置密码:

SQL> alter user sys$umf account unlock identified by xxzx7817600;

User altered.

SQL>create table t1 as select * from user_tables;
Table created.

SQL> create index idx_t1_tablename on t1(table_name);

Index created.

SQL> exec dbms_stats.gather_table_stats('sys','t1',degree => 4,cascade => true);

PL/SQL procedure successfully completed.

创建一个备库(cs_dg)到主库的链路,由于ADG是只读的,所以创建数据库链路操作都需要在主库中执行:

SQL> create database link cs_dg2_to_cs2 connect to sys$umf identified by abcd1234 using   'CS';

Database link created.

在备库中验证数据库链路是否创建成功

 col owner for a20
SQL> col object_name for a50
SQL> select owner,object_name from dba_objects where object_type='DATABASE LINK';

OWNER                OBJECT_NAME
-------------------- --------------------------------------------------
SYS                  CS_DG2_TO_CS2
SYS                  SYS_HUB

SQL>  select table_name from user_tables@cs_dg2_to_cs2;

no rows selected

SQL> select sysdate from dual@cs_dg2_to_cs2;

SYSDATE
------------
24-JAN-19

在备库中对表t1执行查询,database_link_to参数用来指定备库到主库的数据链路名cs_dg2_to_cs2

SQL> variable tname varchar2(30);
SQL> variable query varchar2(500);
SQL> exec :tname := 'jy_task';

PL/SQL procedure successfully completed.

SQL> exec :query := 'select /*+ full(t)*/ col1 from t1 t where table_name=''T1''';

PL/SQL procedure successfully completed.

SQL> begin
  2  :tname := dbms_sqltune.create_tuning_task
  3  (
  4  sql_text => :query,
  5  task_name => :tname,
  6  database_link_to => 'CS_DG2_TO_CS2',
  7  scope=>'COMPREHENSIVE',
  8  time_limit=>60,
  9  description=>'Task to tune a query_on adg');
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> exec dbms_sqltune.execute_tuning_task(:tname);

PL/SQL procedure successfully completed.

SQL> select dbms_sqltune.report_tuning_task(:tname) from dual;

DBMS_SQLTUNE.REPORT_TUNING_TASK(:TNAME)
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
----------------------------------------------------

Oracle 12C Statistics on Column Groups

Statistics on Column Groups
单个列统计信息对于判断where子句中的单个谓词的选择性是非常有用的。然而,当where子句中包含来自相同表的不同列的多个谓词时,单个列统计信息不能显示列之间的关系。使用列组(column group)就是用来解决这个问题的。优化器单独计算谓词的选择性,然后合并它们。然而,如果在单列之间存在关联,那么优化器当评估基数时不会考虑它,优化器会使用每个表谓词的选择性来乘以行数来评估基数。

下面的语句查询dba_tab_col_statistics表来显示关于sh.customers表中列cust_state_province与country_id列的统计信息。

SQL> COL COLUMN_NAME FORMAT a20
SQL> COL NDV FORMAT 999
SQL> SELECT COLUMN_NAME, NUM_DISTINCT AS "NDV", HISTOGRAM
  2  FROM DBA_TAB_COL_STATISTICS
  3  WHERE OWNER = 'SH'
  4  AND TABLE_NAME = 'CUSTOMERS'
  5  AND COLUMN_NAME IN ('CUST_STATE_PROVINCE', 'COUNTRY_ID');

COLUMN_NAME           NDV HISTOGRAM
-------------------- ---- ---------------
CUST_STATE_PROVINCE   145 FREQUENCY
COUNTRY_ID             19 FREQUENCY

下面的语句查询住在California的客户人数3341人:

SQL> SELECT COUNT(*)
  2  FROM sh.customers
  3  WHERE cust_state_province = 'CA';

  COUNT(*)
----------
      3341

来显示查询state为CA,country_id为52790(USA)的客户人数的查询执行

SQL> EXPLAIN PLAN FOR
  2  SELECT *
  3  FROM sh.customers
  4  WHERE cust_state_province = 'CA'
  5  AND country_id=52790;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2008213504

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |  1115 |   205K|   423   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |  1115 |   205K|   423   (1)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("CUST_STATE_PROVINCE"='CA' AND "COUNTRY_ID"=52790)

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel thre
shold


17 rows selected.

基于单列country_id和cust_state_province列的统计信息,优化器评估住在USA的California的客户人数是1115,而实际上有3341人,但优化器不知道,所以通过所有谓词减少了返回的行数因此大大降低了评估基数。可以通过收集列组统计信息来让优化器知晓列country_id与cust_state_province之间的真实关系。

自动与手动列组统计信息
Oracle数据库可以自动或手动创建列组统计信息。优化器可以使用SQL执行计划指令来生成更优的执行计划。如果dbms_stats引用参数auto_stat_extensions被设置为ON(缺省值为OFF),那么SQL执行计划指令基于工作量中谓词的使用情况可以自动触发来创建列组统计信息。可以通过set_table_prefs,set_global_prefs或set_schema_prefs过程来设置auto_stat_extensions。

当想要手动管理列组统计信息时,可以使用dbms_stats来执行以下操作:
.探测列组
.创建以前探测到的列组
.手动创建列组并收集列组统计信息

列组统计信息用户接口
有几个dbms_stats程序单元有与列组相关的引用参数
seed_col_usage过程,迭代指定工作量中的SQL语句,编译它们,然后查看在这些语句谓词中出现列的使用信息。为了决定合适的列组,数据库必须观察一个有代表性的工作量。在监控期间不需要运行查询本身。可以对在工作量中那些运行时间长的查询执行explain plan来确保数据库记录这些查询所使用的列组信息。

report_col_usage函数,生成一个报告列出在工作量中所看到的过滤谓词,连接谓词与group by子句中的列。可以使用这个函数来检查对于指定表所记录的列使用信息。

create_extended_stats函数,创建扩展,它可以是列组或表达式。当用户手动或自动统计信息收集任务对表收集统计信息时数据库会对扩展收集统计信息。

auto_stat_extensions引用参数,控制自动创建扩展,包括列组,当优化器统计信息被收集时,使用set_table_prefs,set_schema_prefs或set_global_prefs来设置这个引用参数。当auto_stat_extensions被设置为off(缺省值)时,数据库不会自动创建列组统计信息。为了创建扩展,你必须执行create_extended_stats函数或在dbms_stats API中的method_opt参数中显性指定扩展统计信息。当auto_stat_extensions设置为ON时,一个SQL执行计划指令基于工作量中谓词中列的使用信息可以触发自动创建列组统计信息。

为特定的工作量检测有用的列组
可以使用dbms_stats.seed_col_usage与report_col_usage来基于特定工作量来决定那个表需要列组。当你不知道需要创建什么样的扩展统计信息时这种技术很有用。这种技术对于扩展统计信息不会工作。

假设存在以下情况:
.查询sh.customers_test表(用customers表来创建)并在谓词中使用了country_id与cust_state_province列但基数评估不正确。

.想要数据库监控工作量5分钟(300秒)。

.想要数据库自动判断需要那些列组。

为了检测列组需要执行以下操作:
1.启动SQL*Plus或SQL Developer,并以用户sh登录数据库

2.创建表customers_test并收集统计信息:

SQL> DROP TABLE customers_test;

Table dropped.

SQL> CREATE TABLE customers_test AS SELECT * FROM customers;

Table created.

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(user, 'customers_test');

PL/SQL procedure successfully completed.

3.启用工作量监控
在不同的SQL*Plus会话中,以sys用户登录并执行以下的PL/SQL程序来启用监控300秒:

SQL> BEGIN
  2  DBMS_STATS.SEED_COL_USAGE(null,null,300);
  3  END;
  4  /

PL/SQL procedure successfully completed.

4.以用户sh来在使用工作量的情况下对两个查询解析它们的执行计划。

SQL> EXPLAIN PLAN FOR
  2  SELECT *
  3  FROM customers_test
  4  WHERE cust_city = 'Los Angeles'
  5  AND cust_state_province = 'CA'
  6  AND country_id = 52790;

Explained.

SQL> SELECT PLAN_TABLE_OUTPUT
  2  FROM TABLE(DBMS_XPLAN.DISPLAY('plan_table', null,'basic rows'));
Plan hash value: 2112738156

----------------------------------------------------
| Id  | Operation         | Name           | Rows  |
----------------------------------------------------
|   0 | SELECT STATEMENT  |                |     1 |
|   1 |  TABLE ACCESS FULL| CUSTOMERS_TEST |     1 |
----------------------------------------------------

8 rows selected.

SQL> EXPLAIN PLAN FOR
  2  SELECT country_id, cust_state_province, count(cust_city)
  3  FROM customers_test
  4  GROUP BY country_id, cust_state_province;

Explained.

SQL> SELECT PLAN_TABLE_OUTPUT
  2  FROM TABLE(DBMS_XPLAN.DISPLAY('plan_table', null,'basic rows'));
Plan hash value: 1820398555

-----------------------------------------------------
| Id  | Operation          | Name           | Rows  |
-----------------------------------------------------
|   0 | SELECT STATEMENT   |                |  1949 |
|   1 |  HASH GROUP BY     |                |  1949 |
|   2 |   TABLE ACCESS FULL| CUSTOMERS_TEST | 55500 |
-----------------------------------------------------

9 rows selected.

第一个执行计划显示基数为1而查询返回932行记录,第二个执行计划显示基数为1949而查询返回145行记录。

5.可选操作,检查对表customers_test所记录的列使用信息

SQL> SET LONG 100000
SQL> SET LINES 120
SQL> SET PAGES 0
SQL> SELECT DBMS_STATS.REPORT_COL_USAGE(user, 'customers_test')
  2  FROM DUAL;
LEGEND:
.......

EQ         : Used in single table EQuality predicate
RANGE      : Used in single table RANGE predicate
LIKE       : Used in single table LIKE predicate
NULL       : Used in single table is (not) NULL predicate
EQ_JOIN    : Used in EQuality JOIN predicate
NONEQ_JOIN : Used in NON EQuality JOIN predicate
FILTER     : Used in single table FILTER predicate
JOIN       : Used in JOIN predicate
GROUP_BY   : Used in GROUP BY expression
...............................................................................

###############################################################################

COLUMN USAGE REPORT FOR SH.CUSTOMERS_TEST
.........................................

1. COUNTRY_ID                          : EQ
2. CUST_CITY                           : EQ
3. CUST_STATE_PROVINCE                 : EQ
4. (CUST_CITY, CUST_STATE_PROVINCE,
    COUNTRY_ID)                        : FILTER
5. (CUST_STATE_PROVINCE, COUNTRY_ID)   : GROUP_BY
###############################################################################

在上面的报告中,前三个列是第一个监控查询中等值谓词中所使用的三个列:

...
WHERE cust_city = 'Los Angeles'
AND cust_state_province = 'CA'
AND country_id = 52790;

所有三个列出现在相同的where子句中,因此报告显示他们作为一组。在第二个查询中,两个列出现在group by子句中,因此报告标记它们作为group_by。在filter与group_by中的列组就是列组的候选者。

在工作量监控下创建所检测到的列组
可以使用dbms_stats.create_extended_stats函数来为执行dbms_stats.seed_col_usage所检测到的列组来创建列组,具体操作如下:
1.基于在监控窗口期间所捕获到的列使用信息来为customers_test表创建列组,执行下面的查询

SQL> SELECT DBMS_STATS.CREATE_EXTENDED_STATS(user, 'customers_test') FROM DUAL;
###############################################################################

EXTENSIONS FOR SH.CUSTOMERS_TEST
................................

1. (CUST_CITY, CUST_STATE_PROVINCE,
    COUNTRY_ID)                        : SYS_STUMZ$C3AIHLPBROI#SKA58H_N created
2. (CUST_STATE_PROVINCE, COUNTRY_ID)   : SYS_STU#S#WF25Z#QAHIHE#MOFFMM_ created
###############################################################################

数据库将为customers_test表创建两个列组:一个列组是过滤谓词,一个列组是group by操作。

2.重新收集表统计信息

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'customers_test');

PL/SQL procedure successfully completed.

3.以用户sh来查询user_tab_col_statistics视图来判断数据库创建了那些额外统计信息:

SQL> SELECT COLUMN_NAME, NUM_DISTINCT, HISTOGRAM
  2  FROM USER_TAB_COL_STATISTICS
  3  WHERE TABLE_NAME = 'CUSTOMERS_TEST'
  4  ORDER BY 1;

COUNTRY_ID                                                   19 FREQUENCY
CUST_CITY                                                   620 HYBRID
CUST_CITY_ID                                                620 NONE
CUST_CREDIT_LIMIT                                             8 NONE
CUST_EFF_FROM                                                 1 NONE
CUST_EFF_TO                                                   0 NONE
CUST_EMAIL                                                 1699 NONE
CUST_FIRST_NAME                                            1300 NONE
CUST_GENDER                                                   2 NONE
CUST_ID                                                   55500 NONE
CUST_INCOME_LEVEL                                            12 NONE
CUST_LAST_NAME                                              908 NONE
CUST_MAIN_PHONE_NUMBER                                    51344 NONE
CUST_MARITAL_STATUS                                          11 NONE
CUST_POSTAL_CODE                                            623 NONE
CUST_SRC_ID                                                   0 NONE
CUST_STATE_PROVINCE                                         145 FREQUENCY
CUST_STATE_PROVINCE_ID                                      145 NONE
CUST_STREET_ADDRESS                                       49900 NONE
CUST_TOTAL                                                    1 NONE
CUST_TOTAL_ID                                                 1 NONE
CUST_VALID                                                    2 NONE
CUST_YEAR_OF_BIRTH                                           75 NONE
SYS_STU#S#WF25Z#QAHIHE#MOFFMM_                              145 NONE
SYS_STUMZ$C3AIHLPBROI#SKA58H_N                              620 HYBRID

25 rows selected.

上面的查询显示了由dbms_stats.create_extended_stats函数所返回的两个列组名。为CUST_CITY, CUST_STATE_PROVINCE和COUNTRY_ID列所创建的列组有一个HYBRID类型的直方图统计信息。

4.再次解析之前的两个查询语句的执行计划

SQL> EXPLAIN PLAN FOR
  2  SELECT *
  3  FROM customers_test
  4  WHERE cust_city = 'Los Angeles'
  5  AND cust_state_province = 'CA'
  6  AND country_id = 52790;

Explained.

SQL> SELECT PLAN_TABLE_OUTPUT
  2  FROM TABLE(DBMS_XPLAN.DISPLAY('plan_table', null,'basic rows'));
Plan hash value: 2112738156

----------------------------------------------------
| Id  | Operation         | Name           | Rows  |
----------------------------------------------------
|   0 | SELECT STATEMENT  |                |   874 |
|   1 |  TABLE ACCESS FULL| CUSTOMERS_TEST |   874 |
----------------------------------------------------

8 rows selected.

SQL> EXPLAIN PLAN FOR
  2  SELECT country_id, cust_state_province, count(cust_city)
  3  FROM customers_test
  4  GROUP BY country_id, cust_state_province;

Explained.

SQL> SELECT PLAN_TABLE_OUTPUT
  2  FROM TABLE(DBMS_XPLAN.DISPLAY('plan_table', null,'basic rows'));
Plan hash value: 1820398555

-----------------------------------------------------
| Id  | Operation          | Name           | Rows  |
-----------------------------------------------------
|   0 | SELECT STATEMENT   |                |   145 |
|   1 |  HASH GROUP BY     |                |   145 |
|   2 |   TABLE ACCESS FULL| CUSTOMERS_TEST | 55500 |
-----------------------------------------------------

9 rows selected.

第一个查询评估的基数是874,要返回的记录数是932,第二个查询评估的基数是145,要返回的记录数是145,这样基数评估的记录数与实际返回的记录已经非常接近了,这就是列组统计信息所带来的好处。

手动创建与收集列组统计信息
在有些情况下,可能知道想要创建的列组。dbms_stats.gather_table_stats函数的method_opt参数可以自动创建与收集列组统计信息。可以通过使用for columns来指定列组从而来创建一个新的列组。

假设存在以下情况:
.想要对sh.customers表上的cust_state_province与country_id列创建列组。

.想要对sh.customers表与新的列组收集统计信息。

手动创建与收集列组统计信息执行以下操作:
1.启动SQL*Plus并以sh用户登录数据库。

2.使用以下PL/SQL程序来创建列组并收集统计信息:

SQL> BEGIN
  2  DBMS_STATS.GATHER_TABLE_STATS( 'sh','customers',
  3  METHOD_OPT => 'FOR ALL COLUMNS SIZE SKEWONLY ' ||
  4  'FOR COLUMNS SIZE SKEWONLY (cust_state_province,country_id)' );
  5  END;
  6  /

PL/SQL procedure successfully completed.

显示列组信息
为了获得列组名,可以使用dbms_stats.show_extended_stats_name函数或数据库视图。也可以使用视图来获得信息比如,distinct值的数量与列组是否有直方图统计信息。
1.启动SQL*Plus并以sh用户登录数据库。

2.为了获得列组名,执行以下PL/SQL程序

SQL> SELECT SYS.DBMS_STATS.SHOW_EXTENDED_STATS_NAME( 'sh','customers',
  2  '(cust_state_province,country_id)' ) col_group_name
  3  FROM DUAL;

COL_GROUP_NAME
------------------------------------
SYS_STU#S#WF25Z#QAHIHE#MOFFMM_

查询user_stat_extensions视图

SQL> SELECT EXTENSION_NAME, EXTENSION
  2  FROM USER_STAT_EXTENSIONS
  3  WHERE TABLE_NAME='CUSTOMERS';
EXTENSION_NAME                                                                                                                   EXTENSION
-----------------------------------------------------------------------                                                          ------------------------------------
SYS_STU#S#WF25Z#QAHIHE#MOFFMM_                                                                                                   ("CUST_STATE_PROVINCE","COUNTRY_ID")

3.查询创建的列组的distinct值的数量并查看是否创建了直方图

SQL> SELECT e.EXTENSION col_group, t.NUM_DISTINCT, t.HISTOGRAM
  2  FROM USER_STAT_EXTENSIONS e, USER_TAB_COL_STATISTICS t
  3  WHERE e.EXTENSION_NAME=t.COLUMN_NAME
  4  AND e.TABLE_NAME=t.TABLE_NAME
  5  AND t.TABLE_NAME='CUSTOMERS';

COL_GROUP                                                                        NUM_DISTINCT HISTOGRAM
----------------------------------------------------------------------           ------------ ---------
("CUST_STATE_PROVINCE","COUNTRY_ID")                                                      145 FREQUENCY

删除列组
可以使用dbms_stats.drop_extended_stats函数来从表中删除列组

SQL> BEGIN
  2  DBMS_STATS.DROP_EXTENDED_STATS( 'sh', 'customers',
  3  '(cust_state_province, country_id)' );
  4  END;
  5  /

PL/SQL procedure successfully completed.

Oracle 12CR2查询转换之表扩展

在表扩展中,对于读取一个分区表部分数据时优化器会生成使用索引的执行计划。基于索引执行计划可以提高性能,但索引维护会增加开锁。在许多数据库中,DML只影响小部分数据。对于频繁更新的表表扩展使用基于索引的执行计划。你可以在以读取为主的数据上创建一个索引,在以频繁变化的数据上消除索引开销。通过这种方式,表扩展在避免索引维护的同时提高了性能。

表扩展工作原理
表分区使用表扩展成为可能。如果在一个分区表上创建一个本地索引,那么优化器可能会标记索引对于特定的分区不可使用。实际有些分区没有创建索引。在表扩展中,优化器将查询转换为一个union all语句,让一些子查询访问创建索引的分区,一些子查询访问没有创建索引的分区。优化器可以为每个分区选择最有效的访问路径,而不管它是否存在于查询所要访问的所有分区中。

优化器不总是会选择表扩展
.表扩展是基于成本
当数据库访问扩展表的每个分区只会跨越union all的所有分支一次,数据库所连接的任何表都是在分支中被访问。

.语义问题可能导致表扩展无效
例如,一个表出现在一个外连接的右边对于表扩展来说是无效的。

可以使用expand_table hint来控制表扩展。这个hint会覆盖基于成本的决策,但不会覆盖语义检查。

表扩展使用场景
优化器基于查询中出现的谓词条件对每个表必须被访问的分区保持跟踪。分区裁剪能让优化器使用表扩展来生成更有效的执行计划。

下面的例子假设满足以下条件:
.想要对sh.sales表执行星型查询,表sh.sales是基于time_id列进行范围分区的一个分区表。

.想要禁用特定分区上的索引来查看表扩展的优点。

操作步骤如下:
1.以sh用户登录数据库

[oracle@jytest1 ~]$ sqlplus sh/*****@jypdb

SQL*Plus: Release 12.2.0.1.0 Production on Wed Oct 31 18:09:54 2018

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Last Successful login time: Wed Oct 24 2018 17:00:11 +08:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> 

2.执行以下查询

SQL> select *  from sales where time_id >= to_date('2000-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') and prod_id = 38;
...........
        38       2470 24-DEC-01             2        999             1       31.47
        38      13440 24-DEC-01             2        999             1       31.47
        38        490 28-DEC-01             2        999             1       31.47
        38       8406 28-DEC-01             2        999             1       31.47
        38       1466 31-DEC-01             3        351             1       31.47
        38       4340 31-DEC-01             3        351             1       31.47
        38      10658 31-DEC-01             3        351             1       31.47
        38      11390 31-DEC-01             3        351             1       31.47
        38      23226 31-DEC-01             3        351             1       31.47

4224 rows selected.

3.查询执行计划

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced allstats last runstats_last peeked_binds'));
SQL_ID  214qgysqqz0k8, child number 0
-------------------------------------
select *  from sales where time_id >= to_date('2000-01-01 00:00:00',
'syyyy-mm-dd hh24:mi:ss') and prod_id = 38

Plan hash value: 2342444420

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |                |      1 |        |       |   224 (100)|          |       |       |   4224 |00:00:00.03 |     334 |
|   1 |  PARTITION RANGE ITERATOR                  |                |      1 |   5078 |   143K|   224   (0)| 00:00:01 |    13 |    28 |   4224 |00:00:00.03 |     334 |
|   2 |   TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| SALES          |     16 |   5078 |   143K|   224   (0)| 00:00:01 |    13 |    28 |   4224 |00:00:00.02 |     334 |
|   3 |    BITMAP CONVERSION TO ROWIDS             |                |      8 |        |       |            |          |       |       |   4224 |00:00:00.01 |      24 |
|*  4 |     BITMAP INDEX SINGLE VALUE              | SALES_PROD_BIX |      8 |        |       |            |          |    13 |    28 |      8 |00:00:00.01 |      24 |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / SALES@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SEL$1")
      BITMAP_TREE(@"SEL$1" "SALES"@"SEL$1" AND(("SALES"."PROD_ID")))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SEL$1" "SALES"@"SEL$1")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("PROD_ID"=38)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   2 - "PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   3 - "SALES".ROWID[ROWID,10], "PROD_ID"[NUMBER,22]
   4 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "PROD_ID"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold


58 rows selected.

在执行计划中的Pstart与Pstop列,显示了优化器判断只需要访问表的13到28分区。在优化器已经判断了被访问的分区之后,它将考虑所有这些分区上可以使用的索引。在上面的执行计划中,优化器选择使用sales_prod_bix位图索引

4.禁用sales表中sales_1995分区上的索引;

SQL> alter index sales_prod_bix modify partition sales_1995 unusable;

Index altered.

5.再次执行之前的查询语句,然后显示执行计划,可以看到执行计划变成了由两个子查询组成的union all语句,第一个子查询还是对13-28分区使用索引,第二个子查询步骤对应的Pstart与Pstop为invalid,id=11的过滤条件为”PROD_ID”=38,id=9的过滤条件为”SALES”.”TIME_ID”=TO_DATE(‘ 2000-01-01 00:00:00’, ‘syyyy-mm-dd hh24:mi:ss’)))这个过滤条件是为否的,所以过滤后的记录为0,从对应的A-Rows列也可以看到记录为0

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced allstats last runstats_last peeked_binds'));
SQL_ID  214qgysqqz0k8, child number 0
-------------------------------------
select *  from sales where time_id >= to_date('2000-01-01 00:00:00',
'syyyy-mm-dd hh24:mi:ss') and prod_id = 38

Plan hash value: 238952339

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                     | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                              |                |      1 |        |       |   224 (100)|          |       |       |   4224 |00:00:00.05 |     334 |
|   1 |  VIEW                                         | VW_TE_2        |      1 |   5079 |   431K|   224   (0)| 00:00:01 |       |       |   4224 |00:00:00.05 |     334 |
|   2 |   UNION-ALL                                   |                |      1 |        |       |            |          |       |       |   4224 |00:00:00.05 |     334 |
|   3 |    PARTITION RANGE ITERATOR                   |                |      1 |   5078 |   143K|   224   (0)| 00:00:01 |    13 |    28 |   4224 |00:00:00.03 |     334 |
|   4 |     TABLE ACCESS BY LOCAL INDEX ROWID BATCHED | SALES          |     16 |   5078 |   143K|   224   (0)| 00:00:01 |    13 |    28 |   4224 |00:00:00.02 |     334 |
|   5 |      BITMAP CONVERSION TO ROWIDS              |                |      8 |        |       |            |          |       |       |   4224 |00:00:00.01 |      24 |
|*  6 |       BITMAP INDEX SINGLE VALUE               | SALES_PROD_BIX |      8 |        |       |            |          |    13 |    28 |      8 |00:00:00.01 |      24 |
|*  7 |    FILTER                                     |                |      1 |        |       |            |          |       |       |      0 |00:00:00.01 |       0 |
|   8 |     PARTITION RANGE EMPTY                     |                |      0 |      1 |    29 |     1   (0)| 00:00:01 |INVALID|INVALID|      0 |00:00:00.01 |       0 |
|*  9 |      TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| SALES          |      0 |      1 |    29 |     1   (0)| 00:00:01 |INVALID|INVALID|      0 |00:00:00.01 |       0 |
|  10 |       BITMAP CONVERSION TO ROWIDS             |                |      0 |        |       |            |          |       |       |      0 |00:00:00.01 |       0 |
|* 11 |        BITMAP INDEX SINGLE VALUE              | SALES_PROD_BIX |      0 |        |       |            |          |INVALID|INVALID|      0 |00:00:00.01 |       0 |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SET$D0A14387   / VW_TE_2@SEL$0A5B0FFE
   2 - SET$D0A14387
   3 - SET$D0A14387_1
   4 - SET$D0A14387_1 / SALES@SEL$1
   7 - SET$D0A14387_2
   9 - SET$D0A14387_2 / SALES@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SET$D0A14387_2")
      OUTLINE_LEAF(@"SET$D0A14387_1")
      OUTLINE_LEAF(@"SET$D0A14387")
      EXPAND_TABLE(@"SEL$1" "SALES"@"SEL$1")
      OUTLINE_LEAF(@"SEL$0A5B0FFE")
      OUTLINE(@"SET$D0A14387")
      EXPAND_TABLE(@"SEL$1" "SALES"@"SEL$1")
      OUTLINE(@"SEL$1")
      NO_ACCESS(@"SEL$0A5B0FFE" "VW_TE_2"@"SEL$0A5B0FFE")
      BITMAP_TREE(@"SET$D0A14387_1" "SALES"@"SEL$1" AND(("SALES"."PROD_ID")))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SET$D0A14387_1" "SALES"@"SEL$1")
      BITMAP_TREE(@"SET$D0A14387_2" "SALES"@"SEL$1" AND(("SALES"."PROD_ID")))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SET$D0A14387_2" "SALES"@"SEL$1")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("PROD_ID"=38)
   7 - filter(NULL IS NOT NULL)
   9 - filter(("SALES"."TIME_ID"=TO_DATE(' 2000-01-01 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss')))
  11 - access("PROD_ID"=38)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "ITEM_1"[NUMBER,22], "ITEM_2"[NUMBER,22], "ITEM_3"[DATE,7], "ITEM_4"[NUMBER,22], "ITEM_5"[NUMBER,22], "ITEM_6"[NUMBER,22], "ITEM_7"[NUMBER,22]
   2 - STRDEF[22], STRDEF[22], STRDEF[7], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[22]
   3 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   4 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   5 - "SALES".ROWID[ROWID,10], "SALES"."PROD_ID"[NUMBER,22]
   6 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "SALES"."PROD_ID"[NUMBER,22]
   7 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   8 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   9 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
  10 - "SALES".ROWID[ROWID,10], "SALES"."PROD_ID"[NUMBER,22]
  11 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "SALES"."PROD_ID"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold


93 rows selected.

6.禁用分区28上的索引(sales_q4_2003),它是查询需要访问的一个分区:

SQL> alter index sales_prod_bix modify partition sales_q4_2003 unusable;

Index altered.

SQL> alter index sales_time_bix modify partition sales_q4_2003 unusable;

Index altered.

通过禁用查询需要访问分区上的索引,查询将不能再使用这些索引。

7.再次执行查询语句,其执行计划如下,执行计划变成了由三个子查询组成的union all语句,相比之前查询多的第三个子查询对表sales的第28个分区执行全表扫描,这里没有索引可用,因为已经禁用28分区上的索引了。

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced allstats last runstats_last peeked_binds'));
SQL_ID  214qgysqqz0k8, child number 0
-------------------------------------
select *  from sales where time_id >= to_date('2000-01-01 00:00:00',
'syyyy-mm-dd hh24:mi:ss') and prod_id = 38

Plan hash value: 3857158179

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                     | Name           | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |   A-Time   | Buffers | Reads  |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                              |                |      1 |        |       |   225 (100)|          |       |       |   4224 |00:00:00.20 |     334 |     44 |
|   1 |  VIEW                                         | VW_TE_2        |      1 |   5080 |   431K|   225   (0)| 00:00:01 |       |       |   4224 |00:00:00.20 |     334 |     44 |
|   2 |   UNION-ALL                                   |                |      1 |        |       |            |          |       |       |   4224 |00:00:00.19 |     334 |     44 |
|   3 |    PARTITION RANGE ITERATOR                   |                |      1 |   5078 |   143K|   223   (0)| 00:00:01 |    13 |    27 |   4224 |00:00:00.17 |     334 |     44 |
|   4 |     TABLE ACCESS BY LOCAL INDEX ROWID BATCHED | SALES          |     15 |   5078 |   143K|   223   (0)| 00:00:01 |    13 |    27 |   4224 |00:00:00.16 |     334 |     44 |
|   5 |      BITMAP CONVERSION TO ROWIDS              |                |      8 |        |       |            |          |       |       |   4224 |00:00:00.03 |      24 |     16 |
|*  6 |       BITMAP INDEX SINGLE VALUE               | SALES_PROD_BIX |      8 |        |       |            |          |    13 |    27 |      8 |00:00:00.03 |      24 |     16 |
|*  7 |    FILTER                                     |                |      1 |        |       |            |          |       |       |      0 |00:00:00.01 |       0 |      0 |
|   8 |     PARTITION RANGE EMPTY                     |                |      0 |      1 |    29 |     1   (0)| 00:00:01 |INVALID|INVALID|      0 |00:00:00.01 |       0 |      0 |
|*  9 |      TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| SALES          |      0 |      1 |    29 |     1   (0)| 00:00:01 |INVALID|INVALID|      0 |00:00:00.01 |       0 |      0 |
|  10 |       BITMAP CONVERSION TO ROWIDS             |                |      0 |        |       |            |          |       |       |      0 |00:00:00.01 |       0 |      0 |
|* 11 |        BITMAP INDEX SINGLE VALUE              | SALES_PROD_BIX |      0 |        |       |            |          |INVALID|INVALID|      0 |00:00:00.01 |       0 |      0 |
|  12 |    PARTITION RANGE SINGLE                     |                |      1 |      1 |    87 |     2   (0)| 00:00:01 |    28 |    28 |      0 |00:00:00.01 |       0 |      0 |
|* 13 |     TABLE ACCESS FULL                         | SALES          |      1 |      1 |    87 |     2   (0)| 00:00:01 |    28 |    28 |      0 |00:00:00.01 |       0 |      0 |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SET$D0A14387   / VW_TE_2@SEL$0A5B0FFE
   2 - SET$D0A14387
   3 - SET$D0A14387_1
   4 - SET$D0A14387_1 / SALES@SEL$1
   7 - SET$D0A14387_2
   9 - SET$D0A14387_2 / SALES@SEL$1
  12 - SET$D0A14387_3
  13 - SET$D0A14387_3 / SALES@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SET$D0A14387_3")
      OUTLINE_LEAF(@"SET$D0A14387_2")
      OUTLINE_LEAF(@"SET$D0A14387_1")
      OUTLINE_LEAF(@"SET$D0A14387")
      EXPAND_TABLE(@"SEL$1" "SALES"@"SEL$1")
      OUTLINE_LEAF(@"SEL$0A5B0FFE")
      OUTLINE(@"SET$D0A14387")
      EXPAND_TABLE(@"SEL$1" "SALES"@"SEL$1")
      OUTLINE(@"SEL$1")
      NO_ACCESS(@"SEL$0A5B0FFE" "VW_TE_2"@"SEL$0A5B0FFE")
      BITMAP_TREE(@"SET$D0A14387_1" "SALES"@"SEL$1" AND(("SALES"."PROD_ID")))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SET$D0A14387_1" "SALES"@"SEL$1")
      BITMAP_TREE(@"SET$D0A14387_2" "SALES"@"SEL$1" AND(("SALES"."PROD_ID")))
      BATCH_TABLE_ACCESS_BY_ROWID(@"SET$D0A14387_2" "SALES"@"SEL$1")
      FULL(@"SET$D0A14387_3" "SALES"@"SEL$1")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("PROD_ID"=38)
   7 - filter(NULL IS NOT NULL)
   9 - filter(("SALES"."TIME_ID"=TO_DATE(' 2000-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')))
  11 - access("PROD_ID"=38)
  13 - filter("PROD_ID"=38)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "ITEM_1"[NUMBER,22], "ITEM_2"[NUMBER,22], "ITEM_3"[DATE,7], "ITEM_4"[NUMBER,22], "ITEM_5"[NUMBER,22], "ITEM_6"[NUMBER,22], "ITEM_7"[NUMBER,22]
   2 - STRDEF[22], STRDEF[22], STRDEF[7], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[22]
   3 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   4 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   5 - "SALES".ROWID[ROWID,10], "SALES"."PROD_ID"[NUMBER,22]
   6 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "SALES"."PROD_ID"[NUMBER,22]
   7 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   8 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
   9 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
  10 - "SALES".ROWID[ROWID,10], "SALES"."PROD_ID"[NUMBER,22]
  11 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "SALES"."PROD_ID"[NUMBER,22]
  12 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]
  13 - "SALES"."PROD_ID"[NUMBER,22], "SALES"."CUST_ID"[NUMBER,22], "SALES"."TIME_ID"[DATE,7], "SALES"."CHANNEL_ID"[NUMBER,22], "SALES"."PROMO_ID"[NUMBER,22],
       "SALES"."QUANTITY_SOLD"[NUMBER,22], "SALES"."AMOUNT_SOLD"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold


103 rows selected.

Oracle 12CR2查询转换之cursor-duration临时表

在Oracle12C中为了物化查询的中间结果,Oracle数据库在查询编译时在内存中可能会隐式的创建一个cursor_duration临时表。

Cursor-Duration临时表的作用
复杂查询有时会处理相同查询块多次,这将会增加不必要的性能开锁。为了避免这种问题,Oracle数据库可以在游标生命周期内为查询结果创建临时表并存储在内存中。对于有with子句查询,星型转换与分组集合操作的复杂操作,这种优化增强了使用物化中间结果来优化子查询。在这种方式下,cursor-duration临时表提高了性能并且优化了I/O。

Cursor-Duration临时表工作原理
cursor-definition临时表定义内置在内存中。表定义与游标相关,并且只对执行游标的会话可见。当使用cursor-duration临时表时,数据库将执行以下操作:
1.选择使用cursor-duration临时表的执行计划
2.创建临时表时使用唯一名
3.重写查询引用临时表
4.加载数据到内存中直到没有内存可用,在这种情次品下将在磁盘上创建临时段
5.执行查询,从临时表中返回数据
6.truncate表,释放内存与任何磁盘上的临时段

注意,cursor-duration临时表的元数据只要cursor在内存中就会一直存在于内存中。元数据不会存储在数据字典中这意味着通过数据字典视图将不能查询到,不能显性地删除元数据。上面的场景依赖于可用的内存。对于特定查询,临时表使用PGA内存。

cursor-duration临时表的实现类似于排序。如果没有可用内存,那么数据库将把数据写入临时段。对于cursor-duration临时表,主要差异如下:
.在查询结束时数据库释放内存与临时段而不是当row source不现活动时释放。

.内存中的数据仍然存储在内存中,不像排序数据可能在内存与临时段之间移动。
当数据库使用cursor-duration临时表时,关键字cursor duration memory会出现在执行计划中。

cursor-duration临时表使用场景
一个with查询重复相同子查询多次可能有时使用cursor-duration临时表性能更高,下面的查询使用一个with子句来创建三个子查询块:

SQL> set long 99999
SQL> set linesize 300
SQL> with
  2  q1 as (select department_id, sum(salary) sum_sal from hr.employees group by
  3  department_id),
  4  q2 as (select * from q1),
  5  q3 as (select department_id, sum_sal from q1)
  6  select * from q1
  7  union all
  8  select * from q2
  9  union all
 10  select * from q3;

DEPARTMENT_ID    SUM_SAL
------------- ----------
          100      51608
           30      24900
                    7000
           90      58000
           20      19000
           70      10000
          110      20308
           50     156400
           80     304500
           40       6500
           60      28800
           10       4400
          100      51608
           30      24900
                    7000
           90      58000
           20      19000
           70      10000
          110      20308
           50     156400
           80     304500
           40       6500
           60      28800
           10       4400
          100      51608
           30      24900
                    7000
           90      58000
           20      19000
           70      10000
          110      20308
           50     156400
           80     304500
           40       6500
           60      28800
           10       4400

36 rows selected.

下面是优化转换后的执行计划

SQL> select * from table(dbms_xplan.display_cursor(format=>'basic +rows +cost'));

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
EXPLAINED SQL STATEMENT:
------------------------
with q1 as (select department_id, sum(salary) sum_sal from hr.employees
group by department_id), q2 as (select * from q1), q3 as (select
department_id, sum_sal from q1) select * from q1 union all select *
from q2 union all select * from q3

Plan hash value: 4087957524

----------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                       | Rows  | Cost (%CPU)|

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |                            |       |     6 (100)|
|   1 |  TEMP TABLE TRANSFORMATION               |                            |       |            |
|   2 |   LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9E08D2_620789C |       |            |
|   3 |    HASH GROUP BY                         |                            |    11 |   276   (2)|
|   4 |     TABLE ACCESS FULL                    | EMPLOYEES                  |   100K|   273   (1)|
|   5 |   UNION-ALL                              |                            |       |            |
|   6 |    VIEW                                  |                            |    11 |     2   (0)|
|   7 |     TABLE ACCESS FULL                    | SYS_TEMP_0FD9E08D2_620789C |    11 |     2   (0)|
|   8 |    VIEW                                  |                            |    11 |     2   (0)|
|   9 |     TABLE ACCESS FULL                    | SYS_TEMP_0FD9E08D2_620789C |    11 |     2   (0)|
|  10 |    VIEW                                  |                            |    11 |     2   (0)|
|  11 |     TABLE ACCESS FULL                    | SYS_TEMP_0FD9E08D2_620789C |    11 |     2   (0)|
----------------------------------------------------------------------------------------------------


26 rows selected.

在上面的执行计划中,在步骤1中的TEMP TABLE TRANSFORMATION指示数据库使用cursor-duration临时表来执行查询。在步骤2中的CURSOR DURATION MEMORY指示数据库使用内存,如果有可用内存,将结果作为临时表SYS_TEMP_0FD9E08D2_620789C来进行存储。如果没有可用内存,那么数据库将临时数据写入磁盘。

Oracle 12CR2查询转换之临时表转换

在12CR2中出现一种新的查询转换技术临时表转换, 在下面的例子中,数据库对customers表上的子查询结果物化到一个临时表中:

SQL> show parameter star_transformation_enabled
star_transformation_enabled          string      FALSE
SQL> alter session set star_transformation_enabled='true';

Session altered.

SQL> SELECT c.cust_city,
  2  t.calendar_quarter_desc,
  3  SUM(s.amount_sold) sales_amount
  4  FROM sales s,
  5  times t,
  6  customers c,
  7  channels ch
  8  WHERE s.time_id = t.time_id
  9  AND s.cust_id = c.cust_id
 10  AND s.channel_id = ch.channel_id
 11  AND c.cust_state_province = 'CA'
 12  AND ch.channel_desc = 'Internet'
 13  AND t.calendar_quarter_desc IN ('1999-01','1999-02')
 14  GROUP BY c.cust_city, t.calendar_quarter_desc;
Montara                        1999-02      1618.01
Pala                           1999-01      3263.93
Cloverdale                     1999-01        52.64
Cloverdale                     1999-02       266.28
San Francisco                  1999-01      3058.27
San Mateo                      1999-01      8754.59
Los Angeles                    1999-01      1886.19
San Mateo                      1999-02     21399.42
Pala                           1999-02       936.62
El Sobrante                    1999-02      3744.03
El Sobrante                    1999-01      5392.34
Quartzhill                     1999-01        987.3
Legrand                        1999-01        26.32
Pescadero                      1999-01        26.32
Arbuckle                       1999-02        241.2
Quartzhill                     1999-02       412.83
Montara                        1999-01       289.07
Arbuckle                       1999-01       270.08
San Francisco                  1999-02        11257
Los Angeles                    1999-02      2128.59
Pescadero                      1999-02       298.44
Legrand                        1999-02        18.66

22 rows selected.

优化器使用临时表SYS_TEMP_0FD9D6893_63D6F82来代替customers表,并且使用临时表中的相关列来替换所引用的列cust_id和cust_city。数据库创建带有两列(c0 number,c1 varchar2(30))的临时表(从执行计划中的 6 – (rowset=256) “C0″[NUMBER,22], “C1″[VARCHAR2,30]也可以看到)。这些列关联到customers表中的cust_id和cust_city列。

在下面的执行计划中的1,2,3行物化customers子查询到临时表中,在第6行,数据库扫描临时表(代替子查询)来从事实表中构建位图。第27行扫描临时表执行连接返回代替扫描customers表。数据库不用对临时表应用customer表上的过滤条件,因为在物化临时表时已经应用了过滤条件。

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced allstats last runstats_last peeked_binds'));
SQL_ID  a069wzk60bbqd, child number 2
-------------------------------------
SELECT c.cust_city, t.calendar_quarter_desc, SUM(s.amount_sold)
sales_amount FROM sales s, times t, customers c, channels ch WHERE
s.time_id = t.time_id AND s.cust_id = c.cust_id AND s.channel_id =
ch.channel_id AND c.cust_state_province = 'CA' AND ch.channel_desc =
'Internet' AND t.calendar_quarter_desc IN ('1999-01','1999-02') GROUP
BY c.cust_city, t.calendar_quarter_desc

Plan hash value: 2164696140

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name                       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | Pstart| Pstop | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |                            |      1 |        |       |  1177 (100)|          |       |       |     22 |00:00:00.25 |    9080 |     86 |     10 |       |       |          |
|   1 |  TEMP TABLE TRANSFORMATION         |                            |      1 |        |       |            |          |       |       |     22 |00:00:00.25 |    9080 |     86 |     10 |       |       |          |
|   2 |   LOAD AS SELECT                   | SYS_TEMP_0FD9D6893_63D6F82 |      1 |        |       |            |          |       |       |      0 |00:00:00.04 |    1535 |      0 |     10 |  1042K|  1042K|          |
|*  3 |    TABLE ACCESS FULL               | CUSTOMERS                  |      1 |   3341 | 86866 |   423   (1)| 00:00:01 |       |       |   3341 |00:00:00.01 |    1522 |      0 |      0 |       |       |          |
|   4 |   HASH GROUP BY                    |                            |      1 |    877 | 49989 |   754   (1)| 00:00:01 |       |       |     22 |00:00:00.20 |    7538 |     85 |      0 |  1022K|  1022K| 1349K (0)|
|*  5 |    HASH JOIN                       |                            |      1 |  14534 |   809K|   753   (1)| 00:00:01 |       |       |    964 |00:00:00.20 |    7538 |     85 |      0 |  1572K|  1572K| 1696K (0)|
|   6 |     TABLE ACCESS FULL              | SYS_TEMP_0FD9D6893_63D6F82 |      1 |   3341 | 50115 |     4   (0)| 00:00:01 |       |       |   3341 |00:00:00.01 |      18 |     10 |      0 |       |       |          |
|*  7 |     HASH JOIN                      |                            |      1 |  14534 |   596K|   749   (1)| 00:00:01 |       |       |    964 |00:00:00.19 |    7520 |     75 |      0 |  1538K|  1538K| 1685K (0)|
|*  8 |      TABLE ACCESS FULL             | TIMES                      |      1 |    181 |  2896 |    18   (0)| 00:00:01 |       |       |    181 |00:00:00.01 |      65 |      0 |      0 |       |       |          |
|   9 |      VIEW                          | VW_ST_A3F94988             |      1 |  14534 |   369K|   731   (1)| 00:00:01 |       |       |    964 |00:00:00.18 |    7455 |     75 |      0 |       |       |          |
|  10 |       NESTED LOOPS                 |                            |      1 |  14534 |   809K|   706   (1)| 00:00:01 |       |       |    964 |00:00:00.18 |    7455 |     75 |      0 |       |       |          |
|  11 |        PARTITION RANGE SUBQUERY    |                            |      1 |  14534 |   397K|   353   (0)| 00:00:01 |KEY(SQ)|KEY(SQ)|    964 |00:00:00.17 |    7271 |     75 |      0 |       |       |          |
|  12 |         BITMAP CONVERSION TO ROWIDS|                            |      2 |  14534 |   397K|   353   (0)| 00:00:01 |       |       |    964 |00:00:00.16 |    7204 |     75 |      0 |       |       |          |
|  13 |          BITMAP AND                |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.16 |    7204 |     75 |      0 |       |       |          |
|  14 |           BITMAP MERGE             |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.02 |      15 |      5 |      0 |  1024K|   512K| 4096  (0)|
|  15 |            BITMAP KEY ITERATION    |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.02 |      15 |      5 |      0 |       |       |          |
|  16 |             BUFFER SORT            |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.01 |       9 |      0 |      0 | 73728 | 73728 |          |
|* 17 |              TABLE ACCESS FULL     | CHANNELS                   |      1 |      1 |    13 |     3   (0)| 00:00:01 |       |       |      1 |00:00:00.01 |       9 |      0 |      0 |       |       |          |
|* 18 |             BITMAP INDEX RANGE SCAN| SALES_CHANNEL_BIX          |      2 |        |       |            |          |KEY(SQ)|KEY(SQ)|      2 |00:00:00.02 |       6 |      5 |      0 |       |       |          |
|  19 |           BITMAP MERGE             |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.02 |     445 |      9 |      0 |  1024K|   512K|39936  (0)|
|  20 |            BITMAP KEY ITERATION    |                            |      2 |        |       |            |          |       |       |    181 |00:00:00.02 |     445 |      9 |      0 |       |       |          |
|  21 |             BUFFER SORT            |                            |      2 |        |       |            |          |       |       |    362 |00:00:00.01 |      65 |      0 |      0 | 73728 | 73728 |          |
|* 22 |              TABLE ACCESS FULL     | TIMES                      |      1 |    181 |  2896 |    18   (0)| 00:00:01 |       |       |    181 |00:00:00.01 |      65 |      0 |      0 |       |       |          |
|* 23 |             BITMAP INDEX RANGE SCAN| SALES_TIME_BIX             |    362 |        |       |            |          |KEY(SQ)|KEY(SQ)|    181 |00:00:00.02 |     380 |      9 |      0 |       |       |          |
|  24 |           BITMAP MERGE             |                            |      2 |        |       |            |          |       |       |      2 |00:00:00.13 |    6744 |     61 |      0 |  1024K|   512K|45056  (0)|
|  25 |            BITMAP KEY ITERATION    |                            |      2 |        |       |            |          |       |       |    403 |00:00:00.12 |    6744 |     61 |      0 |       |       |          |
|  26 |             BUFFER SORT            |                            |      2 |        |       |            |          |       |       |   6682 |00:00:00.01 |      18 |      0 |      0 |  5512K|   964K|  174K (0)|
|  27 |              TABLE ACCESS FULL     | SYS_TEMP_0FD9D6893_63D6F82 |      1 |   3341 | 16705 |     4   (0)| 00:00:01 |       |       |   3341 |00:00:00.01 |      18 |      0 |      0 |       |       |          |
|* 28 |             BITMAP INDEX RANGE SCAN| SALES_CUST_BIX             |   6682 |        |       |            |          |KEY(SQ)|KEY(SQ)|    403 |00:00:00.10 |    6726 |     61 |      0 |       |       |          |
|  29 |        TABLE ACCESS BY USER ROWID  | SALES                      |    964 |      1 |    29 |   378   (0)| 00:00:01 | ROWID | ROWID |    964 |00:00:00.01 |     184 |      0 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$D5EF7599
   2 - SEL$F6045C7B
   3 - SEL$F6045C7B / C@SEL$F6045C7B
   6 - SEL$D5EF7599 / T1@SEL$9C741BEB
   8 - SEL$D5EF7599 / T@SEL$1
   9 - SEL$5E9A798F / VW_ST_A3F94988@SEL$D5EF7599
  10 - SEL$5E9A798F
  12 - SEL$5E9A798F / S@SEL$1
  17 - SEL$6EE793B7 / CH@SEL$6EE793B7
  22 - SEL$ACF30367 / T@SEL$ACF30367
  27 - SEL$E1F9C76C / T1@SEL$E1F9C76C
  29 - SEL$5E9A798F / SYS_CP_S@SEL$5E9A798F

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
      DB_VERSION('12.2.0.1')
      OPT_PARAM('star_transformation_enabled' 'true')
      ALL_ROWS
      NO_PARALLEL
      OUTLINE_LEAF(@"SEL$F6045C7B")
      OUTLINE_LEAF(@"SEL$ACF30367")
      OUTLINE_LEAF(@"SEL$6EE793B7")
      OUTLINE_LEAF(@"SEL$E1F9C76C")
      OUTLINE_LEAF(@"SEL$5E9A798F")
      TABLE_LOOKUP_BY_NL(@"SEL$0E028FD0" "S"@"SEL$1")
      OUTLINE_LEAF(@"SEL$D5EF7599")
      OUTLINE(@"SEL$1")
      OUTLINE(@"SEL$0E028FD0")
      OUTLINE(@"SEL$C3AF6D21")
      ELIMINATE_JOIN(@"SEL$1" "CH"@"SEL$1")
      OUTLINE(@"SEL$5208623C")
      STAR_TRANSFORMATION(@"SEL$1" "S"@"SEL$1" SUBQUERIES(("T"@"SEL$1") ("CH"@"SEL$1") TEMP_TABLE("C"@"SEL$1")))
      FULL(@"SEL$D5EF7599" "T"@"SEL$1")
      NO_ACCESS(@"SEL$D5EF7599" "VW_ST_A3F94988"@"SEL$D5EF7599")
      FULL(@"SEL$D5EF7599" "T1"@"SEL$9C741BEB")
      LEADING(@"SEL$D5EF7599" "T"@"SEL$1" "VW_ST_A3F94988"@"SEL$D5EF7599" "T1"@"SEL$9C741BEB")
      USE_HASH(@"SEL$D5EF7599" "VW_ST_A3F94988"@"SEL$D5EF7599")
      USE_HASH(@"SEL$D5EF7599" "T1"@"SEL$9C741BEB")
      SWAP_JOIN_INPUTS(@"SEL$D5EF7599" "T1"@"SEL$9C741BEB")
      USE_HASH_AGGREGATION(@"SEL$D5EF7599")
      BITMAP_AND(@"SEL$5E9A798F" "S"@"SEL$1" ("SALES"."CHANNEL_ID") 1)
      BITMAP_AND(@"SEL$5E9A798F" "S"@"SEL$1" ("SALES"."TIME_ID") 2)
      BITMAP_AND(@"SEL$5E9A798F" "S"@"SEL$1" ("SALES"."CUST_ID") 3)
      ROWID(@"SEL$5E9A798F" "SYS_CP_S"@"SEL$5E9A798F")
      LEADING(@"SEL$5E9A798F" "S"@"SEL$1" "SYS_CP_S"@"SEL$5E9A798F")
      SUBQUERY_PRUNING(@"SEL$5E9A798F" "S"@"SEL$1" PARTITION)
      USE_NL(@"SEL$5E9A798F" "SYS_CP_S"@"SEL$5E9A798F")
      FULL(@"SEL$E1F9C76C" "T1"@"SEL$E1F9C76C")
      SEMIJOIN_DRIVER(@"SEL$E1F9C76C")
      FULL(@"SEL$6EE793B7" "CH"@"SEL$6EE793B7")
      SEMIJOIN_DRIVER(@"SEL$6EE793B7")
      FULL(@"SEL$ACF30367" "T"@"SEL$ACF30367")
      SEMIJOIN_DRIVER(@"SEL$ACF30367")
      FULL(@"SEL$F6045C7B" "C"@"SEL$F6045C7B")
      SEMIJOIN_DRIVER(@"SEL$F6045C7B")
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("C"."CUST_STATE_PROVINCE"='CA')
   5 - access("ITEM_1"="C0")
   7 - access("ITEM_2"="T"."TIME_ID")
   8 - filter(("T"."CALENDAR_QUARTER_DESC"='1999-01' OR "T"."CALENDAR_QUARTER_DESC"='1999-02'))
  17 - filter("CH"."CHANNEL_DESC"='Internet')
  18 - access("S"."CHANNEL_ID"="CH"."CHANNEL_ID")
  22 - filter(("T"."CALENDAR_QUARTER_DESC"='1999-01' OR "T"."CALENDAR_QUARTER_DESC"='1999-02'))
  23 - access("S"."TIME_ID"="T"."TIME_ID")
  28 - access("S"."CUST_ID"="C0")

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - "C1"[VARCHAR2,30], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7], SUM("ITEM_3")[22]
   2 - SYSDEF[4], SYSDEF[0], SYSDEF[1], SYSDEF[120], SYSDEF[0]
   3 - "C"."CUST_ID"[NUMBER,22], "C"."CUST_CITY"[VARCHAR2,30], "C"."CUST_STATE_PROVINCE"[VARCHAR2,40]
   4 - "C1"[VARCHAR2,30], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7], SUM("ITEM_3")[22]
   5 - (#keys=1; rowset=256) "C0"[NUMBER,22], "ITEM_1"[NUMBER,22], "C1"[VARCHAR2,30], "T"."TIME_ID"[DATE,7], "ITEM_2"[DATE,7], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7], "ITEM_3"[NUMBER,22]
   6 - (rowset=256) "C0"[NUMBER,22], "C1"[VARCHAR2,30]
   7 - (#keys=1; rowset=256) "T"."TIME_ID"[DATE,7], "ITEM_2"[DATE,7], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7], "ITEM_1"[NUMBER,22], "ITEM_3"[NUMBER,22]
   8 - (rowset=256) "T"."TIME_ID"[DATE,7], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7]
   9 - "ITEM_1"[NUMBER,22], "ITEM_2"[DATE,7], "ITEM_3"[NUMBER,22]
  10 - ROWID[ROWID,10], ROWID[ROWID,10], "S"."CUST_ID"[NUMBER,22], "S"."TIME_ID"[DATE,7], "S"."AMOUNT_SOLD"[NUMBER,22]
  11 - ROWID[ROWID,10]
  12 - ROWID[ROWID,10]
  13 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 32496]
  14 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 32496]
  15 - STRDEF[10], STRDEF[10], STRDEF[7920], "S"."CHANNEL_ID"[NUMBER,22]
  16 - (#keys=2) "CH"."CHANNEL_ID"[NUMBER,22], "CH"."CHANNEL_DESC"[VARCHAR2,20]
  17 - (rowset=256) "CH"."CHANNEL_ID"[NUMBER,22], "CH"."CHANNEL_DESC"[VARCHAR2,20]
  18 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "S"."CHANNEL_ID"[NUMBER,22]
  19 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 32496]
  20 - STRDEF[10], STRDEF[10], STRDEF[7920], "S"."TIME_ID"[DATE,7]
  21 - (#keys=2) "T"."TIME_ID"[DATE,7], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7]
  22 - (rowset=256) "T"."TIME_ID"[DATE,7], "T"."CALENDAR_QUARTER_DESC"[CHARACTER,7]
  23 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "S"."TIME_ID"[DATE,7]
  24 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 32496]
  25 - STRDEF[10], STRDEF[10], STRDEF[7920], "S"."CUST_ID"[NUMBER,22]
  26 - (#keys=1) "C0"[NUMBER,22]
  27 - (rowset=256) "C0"[NUMBER,22]
  28 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 7920], "S"."CUST_ID"[NUMBER,22]
  29 - ROWID[ROWID,10], "S"."CUST_ID"[NUMBER,22], "S"."TIME_ID"[DATE,7], "S"."AMOUNT_SOLD"[NUMBER,22]

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold
   - cbqt star transformation used for this statement
   - this is an adaptive plan