Oracle12c中SQL优化(SQL TUNING)新特性之SQL计划指令
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计划指令的更多相关文章
- Oracle12c中分区(Partition)新特性之TRUNCATEPARTITION和EXCHANGE PARTITION级联功能
TRUNCATE [SUB]PARTITION和EXCHANGE [SUB]PARTITION命令如今可以包括CASCADE子句,从而允许参照分区表向下级联这些操作.为确保该选项正常,相关外键也必须包 ...
- 11g新特性-自动sql调优(Automatic SQL Tuning)
11g新特性-自动sql调优(Automatic SQL Tuning) 在Oracle 10g中,引进了自动sql调优特性.此外,ADDM也会监控捕获高负载的sql语句. 在Oracle 11g中, ...
- SQL Server 2014 BI新特性(一)五个关键点带你了解Excel下的Data Explorer
Data Explorer是即将发布的SQL Server 2014里的一个新特性,借助这个特性讲使企业中的自助式的商业智能变得更加的灵活,从而也降低了商业智能的门槛. 此文是在微软商业智能官方博客里 ...
- 【数据库】 SQL SERVER 2014 实用新特性
[数据库] SQL SERVER 2014 实用新特性 官方链接 一. 内存优化表 大幅提高数据库性能,不过目前没有窗口化设计只能写语句 二. 索引增强
- 【数据库】 SQL SERVER 2012 实用新特性
[数据库] SQL SERVER 2012 实用新特性 官方链接 一. ALWAYS ON - 灾难恢复 二. 列存储索引 - 比非聚集索引效率高,但有索引表不允许修改数据(插入,更新,删除),用于读 ...
- 梁敬彬老师的《收获,不止SQL优化》,关于如何缩短SQL调优时间,给出了三个步骤,
梁敬彬老师的<收获,不止SQL优化>,关于如何缩短SQL调优时间,给出了三个步骤, 1. 先获取有助调优的数据库整体信息 2. 快速获取SQL运行台前信息 3. 快速获取SQL关联幕后信息 ...
- oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)
1. 简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...
- Oracle 11g 中SQL性能优化新特性之SQL性能分析器(SQLPA)
Oracle11g中,真实应用测试选项(the Real Application Testing Option)提供了一个有用的特点,叫SQL性能分析器(SQL Performance Analyze ...
- ABAP 7.50 新特性 – Open SQL中的宿主表达式和其它表达式
在长期的停滞后,Open SQL的发展终于从沉睡中醒来.从ABAP 7.40开始,SAP推进了某些关键的改变,以尽可能地包含SQL92中的特性,并提供与ABAP CDS中的DDL里面的SELECT一样 ...
随机推荐
- python屏幕的交互(读取输出信息)input,raw_input的区别
>>> input("your name?") your name?sam Traceback (most recent call last): File & ...
- Mahout 系列之----共轭梯度
无预处理共轭梯度 要求解线性方程组 ,稳定双共轭梯度法从初始解 开始按以下步骤迭代: 任意选择向量 使得 ,例如, 对 若 足够精确则退出 预处理共轭梯度 预处理通常被用来加速迭代方法的收敛.要使用预 ...
- 百度地图android studio导入开发插件
百度地图SDK v3.5.0开发包下载地址:http://lbsyun.baidu.com/sdk/download?selected=location 开发工具 Android开发工具很多,在这我们 ...
- EBS 系统标准职责定义MAP
ERP的相关职责 Responsibility Name(职责) Application(应用) Responsibility Key(关键字) Data Group(数据组) M ...
- ROS探索总结(十四)——move_base(路径规划)
在上一篇的博客中,我们一起学习了ROS定位于导航的总体框架,这一篇我们主要研究其中最重要的move_base包. 在总体框架图中可以看到,move_base提供了ROS导航的配置.运行.交互接口,它主 ...
- Linux完整备份工具 - dump, restore(现在基本不用这两个)
dump 其实 dump 的功能颇强,他除了可以备份整个文件系统之外,还可以制定等级喔!什么意思啊! 假设你的 /home 是独立的一个文件系统,那你第一次进行过 dump 后,再进行第二次 dump ...
- ZooKeeper 权限管理
这其中一个显而易见的问题就是权限:如果我的数据被别人动了怎么办? 方案一:采用ZooKeeper支持的ACL digest方式,用户自己定义节点的权限 这种方案将zookeeper的acl和diges ...
- HBase Compaction
当 client 向 hregion 端 put() 数据时, HRegion 会判断当前的 memstore 的大小是否大于参数hbase.hregion.memstore.flush.size 值 ...
- 熊猫猪新系统测试之四:Ubuntu 14.04
目前猫猪在办公室一般用的就是乌班图系统,一方面原因是老本本性能跑不起来Windows,更重要的是本猫觉得Linux系统更开放些.况且现在用的也比较熟了,完全可以脱离Windows鸟!这一系列4篇新系统 ...
- Jedis对Redis的常用命令操作
本篇主要总结一些Jedis对Redis的常用命令操作: 1.对key操作命令 2.对String操作命令 3.对List操作命令 4.对Set操作命令 5.对Hash操作命令 6.排序操作指令 一.项 ...