Bullet:ORACLE Using SQL Plan Management(一)
SQL Plan Management如何工作?
当一个SQL硬解析时,基于成本的优化器CBO会生成多个执行计划,并从这些执行计划中选择一个优化器认为最低成本的执行计划。
如果SQL plan baseline生效,优化器会将刚刚生成的执行计划与SQL plan baseline中的执行计划进行比较。
如果该执行计划和基线中的执行计划匹配,且基线中的执行计划标记为可接受(accepted = yes),那么该执行计划将被使用;
如果基线中不存在标记为可接受的执行计划与刚刚生成的执行计划匹配,优化器将评估标记为基线中的可接受的执行计划与当前刚刚生成的执行计划,并选择成本最低的一个。
如果优化器生成的执行计划比当前在基线中的执行计划成本要低,则该执行计划将被添加到基线当中,并标记为一个不可接受的(accepted = no)执行计划,该执行计划不会被直接使用,直到该计划被确认不会引起性能降低。
如果系统变更影响到了所有的可接受的计划,系统会默认这些受影响的计划不可重用,优化器将会使用最低成本的执行计划。
Oracle称这种行为为『保守的计划选择策略』,也即优化器更喜欢选择一个经过测试的执行计划,尽管可能存在一个新的执行计划比当前的执行计划看起来会更加高效。除非这个新的执行计划被证明是更加高效并且标记为可接受的。
SQL plan baseline的使用由OPTIMIZER_USE_SQL_PLAN_BASELINES参数控制,该参数值默认被设置为TRUE,即为使用。访问DBMS_SPM包需要ADMINISTER SQL MANAGEMENT OBJECT权限。
自动捕获
系统是否自动捕获SQL的执行计划基线,是由参数OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES控制,其默认值为FALSE。当该值设置为TRUE的时候,系统将记录SQL语句的执行计划。一个语句的第一个执行计划将被自动标记为可接受的(accepted = yes)。在此之后生成的执行计划将无法呗直接使用,除非被验证不会引起性能降级。性能可被接受的执行计划在演化阶段被添加到执行计划基线当中。
SQL> SHOW PARAMETER OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean FALSE SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE; System altered. SQL> select SQL_TEXT,CREATED,ACCEPTED,ENABLED,FIXED,REPRODUCED,AUTOPURGE from dba_sql_plan_baselines; SQL_TEXT CREATED ACC ENA FIX REP AUT
-------------------------------------------------------------------------------- ------------------------------ --- --- --- --- ---
select count(*) from dba_sql_plan_baselines 08-APR-17 02.16.22.000000 PM YES YES NO YES YES
SELECT SYS.DBMS_ASSERT.SIMPLE_SQL_NAME(PARAMETER_VALUE) FROM MGMT_PARAMETERS WHE 08-APR-17 02.18.02.000000 PM YES YES NO YES YES
DELETE FROM MGMT_JOB_HISTORY H WHERE STEP_ID = :B1 AND NOT EXISTS (SELECT 1 FROM 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
UPDATE MGMT_JOB_EXECUTION SET STEP_STATUS = :B3 WHERE STEP_STATUS = :B2 AND STEP 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
UPDATE MGMT_CURRENT_METRICS SET COLLECTION_TIMESTAMP = :B1 , VALUE = :B6 , STRIN 08-APR-17 02.18.02.000000 PM YES YES NO YES YES
SELECT COUNT(*) FROM MGMT_PARAMETERS WHERE PARAMETER_NAME=:B1 AND UPPER(PARAMETE 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
select SQL_TEXT,CREATED,ACCEPTED,ENABLED,FIXED,REPRODUCED,AUTOPURGE from dba_sql 08-APR-17 02.17.10.000000 PM YES YES NO YES YES
SELECT CONTEXT_TYPE_ID,CONTEXT_TYPE,TRACE_LEVEL,NULL,NULL FROM EMDW_TRACE_CONFIG 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
SELECT PARAMETER_VALUE FROM MGMT_PARAMETERS WHERE PARAMETER_NAME = :B1 08-APR-17 02.16.02.000000 PM YES YES NO YES YES
SELECT target_guid FROM mgmt_metric_dependency WHERE can_calculate = 1 AND 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
SELECT UPPER(PARAMETER_VALUE) FROM MGMT_PARAMETERS WHERE PARAMETER_NAME = :B1 08-APR-17 02.16.02.000000 PM YES YES NO YES YES
SELECT VALUE V FROM WWV_FLOW_PLATFORM_PREFS WHERE NAME = :B1 08-APR-17 02.18.02.000000 PM YES YES NO YES YES
SELECT DISTINCT METRIC_GUID FROM MGMT_METRICS WHERE TARGET_TYPE = :B3 AND METRIC 08-APR-17 02.18.02.000000 PM YES YES NO YES YES
SELECT TO_NUMBER(PARAMETER_VALUE) FROM MGMT_PARAMETERS WHERE PARAMETER_NAME = :B 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
SELECT NVL(ABS(PARAMETER_VALUE),60) FROM MGMT_PARAMETERS WHERE PARAMETER_NAME = 08-APR-17 02.18.02.000000 PM YES YES NO YES YES
SELECT COUNT(FAILOVER_ID) FROM MGMT_FAILOVER_TABLE WHERE SYSDATE-LAST_TIME_STAMP 08-APR-17 02.17.02.000000 PM YES YES NO YES YES
SELECT TARGET_GUID FROM MGMT_TARGETS WHERE TARGET_NAME = :B2 AND TARGET_TYPE = : 08-APR-17 02.18.02.000000 PM YES YES NO YES YES SQL> ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=FALSE; System altered.
不建议在生产环境中开启自动捕获。
除了在SYSTEM级别中更改该参数之外,还可以在SESSION级别中更改。
自动捕获方式原理是 第一次sql语句执行 先查看数据字典看有对应的sqlplan baseline没(用签名查找),没有的话查看一个log(log中有签名,所谓的签名就是将sql语句格式化后的一个标记,可以不分大小写空格之类),没有的话在log中根据sql_text生成一个签 名。第2次执行SQL语句时候 还是先看有对应的sqlplan baselines没,没有的话查看log中有对应的签名没,有的话(此时已经有了),此时才存入sql plan baselines(这个时候存入的执行计划 ,就是你sql语句此时此刻的执行计划,根据统计信息之类算出来的)。所以这个方式为一个sql语句生成sqlplan baseline需要执行2次sql。
如以下示例:
Session 1:
SQL> select sql_handle,SQL_TEXT,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines; no rows selected
此时会话1中,无基线存在。
Session 2:
SQL> alter session set OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES=TRUE; Session altered. SQL> select * from emp where empno=7369; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
会话2中打开自动捕获,并第一次执行我们的语句。
Session 1:
SQL> select sql_handle,SQL_TEXT,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines; no rows selected
此时会话1中,仍无基线存在。
Session 2:
SQL> select * from emp where empno=7369; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
会话2中,再次执行语句。
Session 1:
SQL> select sql_handle,SQL_TEXT,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines; SQL_HANDLE SQL_TEXT ENA ACC FIX
------------------------------ ---------------------------------------- --- --- ---
SQL_353e8c17a551f70c select * from emp where empno=7369 YES YES NO
此时,该会话中可以发现已经捕获了我们执行的SQL语句。
手工加载
手工加载即可以配合自动捕获使用,也可以作为独立的手段使用。加载操作我们用DBMS_SPM包进行操作,既可以从SQL TUNING SETS中加载也可以从Cursor Cache中加载特定的语句。手工加载的被默认标记为可接受的(accepted=yes)。如果该语句已经在基线中存在,则该计划将被添加到执行计划中,否则将新建。
下面的代码演示了使用LOAD_PLANS_FROM_SQLSET函数加载在STS中的SQL语句。加载的过程中可以指定过滤条件。
SET serveroutput ON
DECLARE
my_int pls_integer;
BEGIN
my_int := dbms_spm.load_plans_from_sqlset (
sqlset_name => 'b8rc6j0krxwdc_sqlset_test',
basic_filter => 'sql_id="b8rc6j0krxwdc"',
sqlset_owner => 'SYS',
fixed => 'NO',
enabled => 'YES');
DBMS_OUTPUT.PUT_line(my_int);
END;
/
函数LOAD_PLANS_FROM_CURSOR_CACHE则允许从Cursor Cache进行加载。该函数存在4个重载,可以通过多个条件进行定位,比如SQL_ID,SQL_TEXT,PARSING_SCHEMA_NAME,MODULE和ACTION等。
下面的代码示例演示如何加载:
DECLARE
l_plans_loaded PLS_INTEGER;
BEGIN
l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
sql_id => '12mf9db6pxnmd',PLAN_HASH_VALUE => '');
END;
/
上述代码中演示为指定的SQL_ID和指定的执行计划进行加载。也可以不指定执行计划,那将加载该语句所有的执行计划。
可以注意到的是LOAD_PLANS_FROM_SQLSET和LOAD_PLANS_FROM_CURSOR_CACHE都有一个返回值,该返回值的意思为共加载了多少个执行计划。
显示SQL执行计划基线中的执行计划
视图DBA_SQL_PLAN_BASELINES只存了计划基线的一般信息,而完整的执行计划信息查看则需要通过DBMS_XPLAN包进行查询。
函数DISPLAY_SQL_PLAN_BASELINE将返回格式化好的信息,可以指定一个或者全部的执行计划,共存在3种格式化模式:BASIC、TYPICAL和ALL。
下面演示了之前自动捕获的基线中的执行计划:
SET LONG 10000
SQL> select sql_handle,PLAN_NAME,ENABLED,ACCEPTED,FIXED from dba_sql_plan_baselines; SQL_HANDLE PLAN_NAME ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SQL_353e8c17a551f70c SQL_PLAN_3agnc2ykp3xsc695cc014 YES YES NO SQL> SELECT * FROM TABLE(DBMS_XPLAN.display_sql_plan_baseline(SQL_HANDLE => 'SQL_353e8c17a551f70c', plan_name=>'SQL_PLAN_3agnc2ykp3xsc695cc014', FORMAT => 'ALL')); --------------------------------------------------------------------------------
SQL handle: SQL_353e8c17a551f70c
SQL text: select * from emp where empno=7369
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Plan name: SQL_PLAN_3agnc2ykp3xsc695cc014 Plan id: 1767686164
Enabled: YES Fixed: NO Accepted: YES Origin: AUTO-CAPTURE
-------------------------------------------------------------------------------- Plan hash value: 2949544139 --------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 38 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 38 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id):
------------------------------------------------------------- 1 - SEL$1 / EMP@SEL$1
2 - SEL$1 / EMP@SEL$1 Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("EMPNO"=7369) Column Projection Information (identified by operation id):
----------------------------------------------------------- 1 - "EMPNO"[NUMBER,22], "EMP"."ENAME"[VARCHAR2,10],
"EMP"."JOB"[VARCHAR2,9], "EMP"."MGR"[NUMBER,22], "EMP"."HIREDATE"[DATE,7],
"EMP"."SAL"[NUMBER,22], "EMP"."COMM"[NUMBER,22], "EMP"."DEPTNO"[NUMBER,22]
2 - "EMP".ROWID[ROWID,10], "EMPNO"[NUMBER,22]
更改执行计划基线
ALTER_SQL_PLAN_BASELINE函数提供了更改基线内执行计划的属性的方法。
属性有如下几个:
- enabled(YES/NO):值为YES时,执行计划对优化器来说是可用的,真正被使用时他的另外的属性要被标记为accepted。
- fixed(YES/NO):值为YES时,基线将不会随时间进行演化。相对于非Fixed属性的执行计划,优化器更加青睐有Fixed的属性的执行计划。
- autopurge(YES/NO):值为YES时,如果该执行计划一段时间未被使用,将被自动清除。
- plan_name:用于重命名基线中的sql_plan_name,最多30个字符。
- description:用于修改基线中执行计划的描述信息,最多30个字符。
如下演示了如何将一个执行计划的属性fixed标记为YES。
SQL> select SQL_HANDLE,PLAN_NAME,DESCRIPTION,ENABLED,ACCEPTED,FIXED,AUTOPURGE from dba_sql_plan_baselines; SQL_HANDLE PLAN_NAME DESCRIPTION ENA ACC FIX AUT
------------------------------ ------------------------------ ------------------------------ --- --- --- ---
SQL_353e8c17a551f70c SQL_PLAN_3agnc2ykp3xsc695cc014 YES YES NO YES SQL>
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_plans_altered PLS_INTEGER;
3 BEGIN
4 l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
5 sql_handle => 'SQL_353e8c17a551f70c',
6 plan_name => 'SQL_PLAN_3agnc2ykp3xsc695cc014',
7 attribute_name => 'fixed',
8 attribute_value => 'YES');
9
10 DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
11 END;
12 /
Plans Altered: 1 PL/SQL procedure successfully completed. SQL> select SQL_HANDLE,PLAN_NAME,DESCRIPTION,ENABLED,ACCEPTED,FIXED,AUTOPURGE from dba_sql_plan_baselines; SQL_HANDLE PLAN_NAME DESCRIPTION ENA ACC FIX AUT
------------------------------ ------------------------------ ------------------------------ --- --- --- ---
SQL_353e8c17a551f70c SQL_PLAN_3agnc2ykp3xsc695cc014 YES YES YES YES
配置SPM
SPM的库存放于SYSAUX表空间,存储了SQL PLAN BASELINES,以及语句LOG、计划历史和SQL PROFILE。其空间的使用有两个键值对属性控制,可以通过DBMS_SPM.CONFIGURE进行配置管理。
参数如下:
- space_budget_percent(10):占用SYSAUX表空间的最大使用量。百分比,值允许的范围为1-50.
- plan_retention_weeks(53):那些无用的执行计划在保留多久之后会被清除掉。允许的值范围为5-523,单位周。
其配置可以通过视图DBA_SQL_MANAGEMENT_CONFIG进行查询。
下面的代码演示如何更改配置参数:
SQL> select * from dba_sql_management_config; PARAMETER_NAME PARAMETER_VALUE LAST_MODIFIED MODIFIED_BY
------------------------------ --------------- ------------------------------ ------------------------------
SPACE_BUDGET_PERCENT 10
PLAN_RETENTION_WEEKS 53 SQL> show user
USER is "SYS"
SQL> BEGIN
2 DBMS_SPM.configure('space_budget_percent', 11);
3 DBMS_SPM.configure('plan_retention_weeks', 54);
4 END;
5 / PL/SQL procedure successfully completed. SQL> select * from dba_sql_management_config; PARAMETER_NAME PARAMETER_VALUE LAST_MODIFIED MODIFIED_BY
------------------------------ --------------- ------------------------------ ------------------------------
SPACE_BUDGET_PERCENT 11 2017-04-08 16:50:12 SYS
PLAN_RETENTION_WEEKS 54 2017-04-08 16:50:12 SYS
删除计划基线
DROP_SQL_PLAN_BASELINE函数可以删除一个或者多个执行计划,如果未指定plan name的时候,将删除所有的对应执行计划。
示例如下:
SQL> select SQL_HANDLE,PLAN_NAME,DESCRIPTION,ENABLED,ACCEPTED,FIXED,AUTOPURGE from dba_sql_plan_baselines; SQL_HANDLE PLAN_NAME DESCRIPTION ENA ACC FIX AUT
------------------------------ ------------------------------ ------------------------------ --- --- --- ---
SQL_353e8c17a551f70c SYK SPM DEMO YES YES YES YES SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_plans_dropped PLS_INTEGER;
3 BEGIN
4 l_plans_dropped := DBMS_SPM.drop_sql_plan_baseline (
5 sql_handle => 'SQL_353e8c17a551f70c',
6 plan_name => 'SYK SPM DEMO');
7
8 DBMS_OUTPUT.put_line(l_plans_dropped);
9 END;
10 /
1 PL/SQL procedure successfully completed. SQL> select SQL_HANDLE,PLAN_NAME,DESCRIPTION,ENABLED,ACCEPTED,FIXED,AUTOPURGE from dba_sql_plan_baselines; no rows selected
Bullet:ORACLE Using SQL Plan Management(一)的更多相关文章
- Oracle 固定执行计划-使用SPM(Sql Plan Management)固定执行计划
固定执行计划-使用SPM(Sql Plan Management)固定执行计划 转载自:http://www.lunar2013.com/2016/01/固定执行计划-使用spm%EF%BC%88sq ...
- Oracle 11g 新特性 --SQL Plan Management 说明
Oracle 11g 新特性 --SQL Plan Management 说明 参见大神博主文章: http://blog.csdn.net/tianlesoftware/article/detail ...
- oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)
1. 简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...
- 11g新特性-SQL Plan Management
在11g之前版本,提供了stored outlines(sql概要)特性来保存sql的执行计划. 在11g中,引入了一个新的特性sql计划管理(sql plan management)特性来保存sql ...
- 11g的新特性:SQL Plan Management(SPM)
Oracle11g中,Oracle提供dbms_spm包来管理SQL Plan,SPM是一个预防机制,它记录并评估sql的执行计划,将已知的高效的sql执行计划建立为SQL Plan Baseline ...
- PLSQL_性能优化工具系列09_SQL Plan Management
2014-09-24 Created By BaoXinjian
- 官方文档:11G新特性SQL PLAN BASLINE 执行计划基线
什么是SQL执行计划管理? SQL计划管理(SQL plan management)是一咱预防机制,记录和评估SQL语句的执行计划.SQL plan management的主要功能是sql plan ...
- Oracle SQL操作计划基线总结(SQL Plan Baseline)
一.基础概念 Oracle 11g開始,提供了一种新的固定运行计划的方法,即SQL plan baseline,中文名SQL运行计划基线(简称基线),能够觉得是OUTLINE(大纲)或者SQL PRO ...
- 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)
基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编 ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...
随机推荐
- ionic开发android App
在win下配置ionic可以参考七月的这篇博客:http://www.cnblogs.com/shikelong/p/4480975.html. 依照七月的思路基本可以创建一个ionic项目了,下面我 ...
- Python获得文件时间戳 异常访问监控 邮件定时提醒
Python获得文件时间戳 异常访问监控 邮件定时提醒
- 利用JFreeChart生成区域图 (5) (转自 JSP开发技术大全)
利用JFreeChart生成区域图 (5) (转自 JSP开发技术大全) 14.5 利用JFreeChart生成区域图 通过JFreeChart插件只能生成普通效果的区域图,利用工厂类ChartFac ...
- 使用Java实现图像分割
为减少动画制作过程中的IO操作,我们可以使用连续动画来改善动画播放效率.如果我们对图像中的每张小图像单独分割成独立的文件,那么当每次要使用这些小图像的时候,我们都得从文件中读取图像信息. 实际上我们可 ...
- Spark 分布式环境---slave节点无法启动(已解决)
soyo@soyo-VPCCB3S1C:~$ start-slaves.sh soyo-slave01: starting org.apache.spark.deploy.worker.Worker, ...
- Enum类的非一般用法汇总(工作中遇到时持续更新)
1. 每个枚举实例定义一套自己的方法示例: 1 @AllArgsConstructor 2 public enum BroadcastTypeEnum { 3 ALL(0, "全站&quo ...
- Wannafly挑战赛29A御坂美琴
传送门 这套题很有意思2333 蠢了--首先先判总共加起来等不等于\(n\),不是的话就不行 然后dfs记录\(n\)不断分下去能分成哪些数,用map记录一下,判断是否所有数都能被分出来就是了 //m ...
- curl 做爬虫 用服务器代理ip
有时候会ip会封锁,所以会用一些模拟代理ip进行抓取测试 从网上找了一下代码 function curl_string ($url,$user_agent,$proxy){ $ch = ...
- [Qt Creator 快速入门] 第0篇 开始学习Qt 与Qt Creator
Qt官方信息 Qt官网:http://qt.digia.com/ Qt开源官网:http://qt-project.org/ Qt最新版本下载:http://qt-project.org/downlo ...
- 题解报告:poj 1321 棋盘问题(dfs)
Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子 ...