SQL计划指令是Oracle12c中自适应查询优化的功能之一。SQL计划指令就像“额外的提醒” ,用以提醒优化器你先前选择了的计划并不是最优的,典型的是因为错误的势评估。错误的势评估往往是由统计信息缺失,统计信息陈旧,复杂的谓词或操作等引起的。SQL计划指令和SQL轮廓(SQL profiles)不同,后者是针对特定语句的,而SQL计划指令和查询表达式关联,因此,它们可以被多个包含匹配查询表达式的语句共享。柱状图或扩展统计信息缺失也许会导致SQL计划指令的产生。

数据库在内部自动管理SQL计划指令。像自动重优化的情况也许会引起SQL计划指令被写入SGA且稍后写到SYSAUX表空间,此时,可以通过DBA_SQL_PLAN_DIRECTIVES和DBA_SQL_PLAN_DIR_OBJECTS视图来查看SQL计划指令。此外,已存在的SQL计划指令也能通过DBMS_SPD包来保存。

1.   设置

确信共享池已经被清空,因此,我们知道在一个干净的系统上进行测试。

CONN sys@pdb1 AS SYSDBA

ALTER SYSTEM FLUSH SHARED_POOL;

下面的测试表包含指示省和市存在的列。这些列上有检查约束,以便告诉优化器这些列被允许的值,此外,这些列上还有索引。通过包括10行A省和90行B省的样本来模拟倾斜严重的数据。

CONN test/test@pdb1

DROP TABLE tab1 PURGE;

CREATE TABLE tab1 (

id               NUMBER,

Province           VARCHAR2(10),

city VARCHAR2(10),

CONSTRAINT tab1_pk PRIMARY KEY (id),

CONSTRAINT tab1_prov_chk CHECK (province IN ('A', 'B')),

CONSTRAINTtab1_city_chk CHECK (city IN ('X', 'Y'))

);

INSERT /*+ APPEND */ INTO tab1

SELECT level, 'A', 'X'

FROM  dual

CONNECT BY level <= 10;

COMMIT;

INSERT /*+ APPEND */ INTO tab1

SELECT 10+level, 'B', 'Y'

FROM  dual

CONNECT BY level <= 90;

COMMIT;

CREATE INDEX tab1_prov_idx ON tab1(province);

CREATE INDEX tab1_city_idx ON tab1(city);

EXEC DBMS_STATS.gather_table_stats(USER,'TAB1');

无论数据都没倾斜,当用默认设置收集统计信息时,不会为这些列创建柱状图。

COLUMN column_name FORMAT A20

SELECT column_id,

column_name,

histogram

FROM  user_tab_columns

WHERE table_name = 'TAB1'

ORDER BY column_id;

COLUMN_ID COLUMN_NAME          HISTOGRAM

---------- -----------------------------------

1 ID                   NONE

2 PROVINCE             NONE

3 CITY                 NONE

SQL>

2.   显示错误的势评估

大家都知道,所有省和市都是关联的。由于优化器并不知道这种关联关系,并且也没柱状图来标示数据的倾斜,接着优化器会利用现有信息尽力为谓词的选择性做出评估。于是,它会假设数据均匀分布在各允许值间且一半行被标为A省且一半被标为B省。如果在两个列之间没任何关联,预期100/2/2=25行被标为即是A省和X市。下列查询查出所有符合该规则的行,且显示返回数据的执行计划,包括预期的和实际的势。

CONN test/test@pdb1

SELECT /*+ GATHER_PLAN_STATISTICS */

*

FROM  tab1

WHERE  province= 'A'

AND    city= 'X';

SET LINESIZE 200 PAGESIZE 100

SELECT * FROMTABLE(DBMS_XPLAN.display_cursor(format => 'allstats last'));

PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------------------------------

SQL_ID 5t8y8p5mpb99j, child number 0

-------------------------------------

SELECT /*+ GATHER_PLAN_STATISTICS */        *FROM   tab1 WHERE  province

= 'A' AND   city = 'X'

Plan hash value: 1552452781

-----------------------------------------------------------------------------------------------------------------

| Id  |Operation                           |Name            | Starts | E-Rows |A-Rows |   A-Time   | Buffers |

-----------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                    |                 |      1 |       |     10 |00:00:00.01 |       4 |

|*  1|  TABLE ACCESS BY INDEX ROWID BATCHED|TAB1            |      1 |    25 |     10 |00:00:00.01 |       4 |

|*  2|   INDEX RANGE SCAN                  | TAB1_PROV_IDX |      1 |    50 |     10 |00:00:00.01 |       2 |

-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified byoperation id):

---------------------------------------------------

1 -filter("CITY"='X')

2 -access("PROVINCE"='A')

SQL>

正如预期的那样,优化器得到了一个错误的势评估。这是一个经典的案例,其中,柱状图,或扩展统计信息,或两者存在将有助于优化器能更精确的对势做出评估。

下列查询检查V$SQL视图的IS_REOPTIMIZABLE列,看优化器是否已注意到错误的势评估。

CONN sys@pdb1 AS SYSDBA

COLUMN sql_text FORMAT A40

COLUMN is_reoptimizable FORMAT A16

SELECT sql_text, is_reoptimizable

FROM  v$sql

WHERE sql_id = '5t8y8p5mpb99j';

SQL_TEXT                                IS_REOPTIMIZABLE

---------------------------------------- ----------------

SELECT /*+ GATHER_PLAN_STATISTICS */

*FROM   tab1 WHERE  province = 'A' AN

D    city= 'X'

SQL>

由于该语句被标作可重新优化的,因此,SQL计划指令也很可能已经被创建了。

3.   显示SQL计划指令

至此,优化器已经把SQL计划指令写入了SGA,但是我们还不能看到它们,因为它们还没被写入SYSAUX表空间。

CONN sys@pdb1 AS SYSDBA

SET LINESIZE 200

COLUMN dir_id FORMAT A20

COLUMN owner FORMAT A10

COLUMN object_name FORMAT A10

COLUMN col_name FORMAT A10

SELECT TO_CHAR(d.directive_id) dir_id,o.owner, o.object_name,

o.subobject_name col_name, o.object_type, d.type, d.state, d.reason

FROM  dba_sql_plan_directives d, dba_sql_plan_dir_objects o

WHERE d.directive_id=o.directive_id

AND   o.owner = 'TEST'

ORDER BY 1,2,3,4,5;

no rows selected

SQL>

我们可以等数据库把SQL计划指令保存,或用DBMS_SPD包手工保存。

CONN sys@pdb1 AS SYSDBA

EXEC DBMS_SPD.flush_sql_plan_directive;

现在我们运行前面的查询,将会看到SQL计划指令。

CONN sys@pdb1 AS SYSDBA

SET LINESIZE 200

COLUMN dir_id FORMAT A20

COLUMN owner FORMAT A10

COLUMN object_name FORMAT A10

COLUMN col_name FORMAT A10

SELECT TO_CHAR(d.directive_id) dir_id,o.owner, o.object_name,

o.subobject_name col_name, o.object_type, d.type, d.state, d.reason

FROM  dba_sql_plan_directives d, dba_sql_plan_dir_objects o

WHERE d.directive_id=o.directive_id

AND   o.owner = 'TEST'

ORDER BY 1,2,3,4,5;

DIR_ID               OWNER     OBJECT_NAM COL_NAME   OBJECTTYPE             STATE      REASON

-------------------- ---------- -------------------- ------ ---------------- ----------------------------------------------

12422623998396966202 TEST       TAB1     PROVINCE     COLUMN DYNAMIC_SAMPLING USABLE     SINGLE TABLE CARDINALITY MISESTIMATE

12422623998396966202 TEST       TAB1                  TABLE  DYNAMIC_SAMPLING USABLE     SINGLE TABLE CARDINALITY MISESTIMATE

SQL>

4.   显示SQL计划指令的使用

下列查询是刚才我们产生SQL计划指令的那个。注意,势评估发生了改变,且在DBMS_XPLAN输出末尾出现了提醒。

CONN test/test@pdb1

SELECT /*+ GATHER_PLAN_STATISTICS */

*

FROM  tab1

WHERE  province= 'A'

AND    city= 'X';

SET LINESIZE 200 PAGESIZE 100

SELECT * FROMTABLE(DBMS_XPLAN.display_cursor(format => 'allstats last'));

PLAN_TABLE_OUTPUT

-----------------------------------------------------------------------------------------------------------------

SQL_ID 5t8y8p5mpb99j, child number 1

-------------------------------------

SELECT /*+ GATHER_PLAN_STATISTICS */        *FROM   tab1 WHERE  province

= 'A' AND   city = 'X'

Plan hash value: 1552452781

-----------------------------------------------------------------------------------------------------------------

| Id  |Operation                           |Name            | Starts | E-Rows |A-Rows |   A-Time   | Buffers |

-----------------------------------------------------------------------------------------------------------------

|   0 |SELECT STATEMENT                   |                 |      1 |       |     10 |00:00:00.01 |       4 |

|*  1|  TABLE ACCESS BY INDEX ROWID BATCHED|TAB1            |      1 |    10 |     10 |00:00:00.01 |       4 |

|*  2|   INDEX RANGE SCAN                  | TAB1_PROV_IDX |      1 |    10 |     10 |00:00:00.01 |       2 |

-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified byoperation id):

---------------------------------------------------

1 -filter("CITY"='X')

2 -access("PROVINCE"='A')

Note

-----

-dynamic statistics used: dynamic sampling (level=2)

-statistics feedback used for this statement

- 1Sql Plan Directive used for this statement

SQL>

5.   SQL 计划指令和统计信息

SQL计划指令典型是一个“丢失信息” 的指示,但这些“丢失的信息”也许将来会变大的可用。如果我们重新收集表TAB1的统计信息,我们会注意到存在倾斜数据的列已被收集了统计信息。

EXEC DBMS_STATS.gather_table_stats(USER,'TAB1');

SELECT column_id,

column_name,

histogram

FROM  user_tab_columns

WHERE table_name = 'TAB1'

ORDER BY column_id;

COLUMN_ID COLUMN_NAME          HISTOGRAM

---------- -----------------------------------

1 ID                   NONE

2 PROVINCE             FREQUENCY

3 CITY                 FREQUENCY

SQL>

如果收集了扩展统计信息,可用下面的语句查看它们。

COLUMN extension FORMAT A30

SELECT extension_name, extension

FROM  user_stat_extensions;

一旦需要的柱状图或扩展信息存在,或如果替代SQL计划指令被创建,则该SQL计划指令也许就会切换到一个替代状态而不再被使用。

CONN sys@pdb1 AS SYDBA

SELECT state, COUNT(*)

FROM  dba_sql_plan_directives

GROUP BY state

ORDER BY state;

STATE       COUNT(*)

---------- ----------

SUPERSEDED         26

USABLE             44

SQL>

默认的,SQL计划指令超过53周不被使用就会被删除。而某些SQL计划指令会对列组统计信息的收集有影响。

6.   DBMS_SPD包

DBMS_SPD包可以在一定程度上控制SQL计划指令。

可以用以下过程来进行基本的SQL计划指令管理。

1)     FLUSH_SQL_PLAN_DIRECTIVE:将SGA中的SQL计划指令存入SYSAUX表空间。

2)     ALTER_SQL_PLAN_DIRECTIVE:更改确定SQL计划指令的ENABLED和AUTO_DROP属性。

3)     DROP_SQL_PLAN_DIRECTIVE:删除确定的SQL计划指令。

SQL计划指令不使用而被保留的最长时间通过 SPD_RETENTION_WEEKS确定,默认为53周。这可以用如下过程显示和修改。

1)     GET_PREFS :显示确定的偏好(preference)。目前只支持SPD_RETENTION_WEEKS。

2)     SET_PREFS :设置确定的偏好(preference)。目前只支持SPD_RETENTION_WEEKS。

SQL计划执行的长期存储和迁移可以用如下过程。

1)     CREATE_STGTAB_DIRECTIVE:创建一个将SQL计划指令导出到的中间表。

2)     PACK_STGTAB_DIRECTIVE:将SQL计划指令导出到指定表。

3)     UNPACK_STGTAB_DIRECTIVE:从中间表导入SQL计划指令。

DBMS_SPD包的很多功能需要ADMINISTER SQL MANAGEMENTOBJECT权限。

7.   注释:

有时SQL计划指令内部管理机制看起来有些混乱。测试期间,我遇到过本来希望它被创建但却没有。也遇到过本希望存在的SQL计划指令标作被替代状态但却没有。开始我认为这可能是因为我忘了保存,但情况似乎并非如此。

记得查询 DBA_SQL_PLAN_DIRECTIVES和DBA_SQL_PLAN_DIR_OBJECTS视图前总是运行DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE过程。

Oracle12c中SQL优化(SQL TUNING)新特性之SQL计划指令的更多相关文章

  1. Oracle12c中分区(Partition)新特性之TRUNCATEPARTITION和EXCHANGE PARTITION级联功能

    TRUNCATE [SUB]PARTITION和EXCHANGE [SUB]PARTITION命令如今可以包括CASCADE子句,从而允许参照分区表向下级联这些操作.为确保该选项正常,相关外键也必须包 ...

  2. 11g新特性-自动sql调优(Automatic SQL Tuning)

    11g新特性-自动sql调优(Automatic SQL Tuning) 在Oracle 10g中,引进了自动sql调优特性.此外,ADDM也会监控捕获高负载的sql语句. 在Oracle 11g中, ...

  3. SQL Server 2014 BI新特性(一)五个关键点带你了解Excel下的Data Explorer

    Data Explorer是即将发布的SQL Server 2014里的一个新特性,借助这个特性讲使企业中的自助式的商业智能变得更加的灵活,从而也降低了商业智能的门槛. 此文是在微软商业智能官方博客里 ...

  4. 【数据库】 SQL SERVER 2014 实用新特性

    [数据库] SQL SERVER 2014 实用新特性 官方链接 一. 内存优化表 大幅提高数据库性能,不过目前没有窗口化设计只能写语句 二. 索引增强

  5. 【数据库】 SQL SERVER 2012 实用新特性

    [数据库] SQL SERVER 2012 实用新特性 官方链接 一. ALWAYS ON - 灾难恢复 二. 列存储索引 - 比非聚集索引效率高,但有索引表不允许修改数据(插入,更新,删除),用于读 ...

  6. 梁敬彬老师的《收获,不止SQL优化》,关于如何缩短SQL调优时间,给出了三个步骤,

    梁敬彬老师的<收获,不止SQL优化>,关于如何缩短SQL调优时间,给出了三个步骤, 1. 先获取有助调优的数据库整体信息 2. 快速获取SQL运行台前信息 3. 快速获取SQL关联幕后信息 ...

  7. oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)

    1.   简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...

  8. Oracle 11g 中SQL性能优化新特性之SQL性能分析器(SQLPA)

    Oracle11g中,真实应用测试选项(the Real Application Testing Option)提供了一个有用的特点,叫SQL性能分析器(SQL Performance Analyze ...

  9. ABAP 7.50 新特性 – Open SQL中的宿主表达式和其它表达式

    在长期的停滞后,Open SQL的发展终于从沉睡中醒来.从ABAP 7.40开始,SAP推进了某些关键的改变,以尽可能地包含SQL92中的特性,并提供与ABAP CDS中的DDL里面的SELECT一样 ...

随机推荐

  1. E-JSON数据传输标准

    简介 E-JSON的设计目标是使业务系统向浏览器端传递的JSON数据保持一致,容易被理解和处理,并兼顾传输的数据量.E-JSON依托于http协议(rfc2616)与JSON数据交换格式(rfc462 ...

  2. (二十四)监听键盘的通知和键盘弹出隐藏的View移动

    让控制器监听键盘的通知,注意谁监听,谁的dealloc方法中就要remove,如果非ARC还要调用父类的dealloc方法. //监听键盘的操作: [[NSNotificationCenter def ...

  3. C++链表模板类

    思想和上篇文章差不多,只是换了层包装. 直接上代码: // linklist.h #include <iostream> #include <cstdio> using nam ...

  4. Xshell Linux 主要命令

    1.   查看当前路径 pwd 2.列出当前目录的文件 ls   列出所有文件或者文件夹 ls  *abc  列出以abc开头的所以文件 ls –l   列出所以文件及其详细详细 3.进入目录 cd  ...

  5. 用curl采集需要登录的页面

    登陆cookie存储至自定义目录 $cookie_dir = tempnam('.', 'cookie');curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_ ...

  6. tomcat会话之持久化会话管理器

    前面提到的标准会话管理器已经提供了基础的会话管理功能,但在持久化方面做得还是不够,或者说在某些情景下无法满足要求,例如把会话以文件或数据库形式存储到存储介质中,这些都是标准会话管理器无法做到的,于是另 ...

  7. IP协议详解(转)

    本文转载自博文协议森林05 我尽力 (IP协议详解).这篇博文写的很有趣味,特转载! IPv4与IPv6头部的对比 我们已经在IP接力中介绍过,一个IP包分为头部(header)和数据(payload ...

  8. android自定义状态栏颜色

    我们知道IOS上的应用,状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定义状态栏背景颜色啦,这是个不错 ...

  9. Erlang cowboy 入门参考

    Erlang cowboy 入门参考 cheungmine,2014-10-28 本文翻译自: http://ninenines.eu/docs/en/cowboy/HEAD/guide/gettin ...

  10. 【Qt编程】3D迷宫游戏

    说起迷宫想必大家都很熟悉,个人感觉迷宫对人的方向感是很大的考验,至少我的方向感是不好的,尤其是在三维空间中.由于这段时间帮导师做项目用到了三维作图,便心血来潮想做个三维迷宫玩玩.要想画出三维的迷宫游戏 ...