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(一)的更多相关文章

  1. Oracle 固定执行计划-使用SPM(Sql Plan Management)固定执行计划

    固定执行计划-使用SPM(Sql Plan Management)固定执行计划 转载自:http://www.lunar2013.com/2016/01/固定执行计划-使用spm%EF%BC%88sq ...

  2. Oracle 11g 新特性 --SQL Plan Management 说明

    Oracle 11g 新特性 --SQL Plan Management 说明 参见大神博主文章: http://blog.csdn.net/tianlesoftware/article/detail ...

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

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

  4. 11g新特性-SQL Plan Management

    在11g之前版本,提供了stored outlines(sql概要)特性来保存sql的执行计划. 在11g中,引入了一个新的特性sql计划管理(sql plan management)特性来保存sql ...

  5. 11g的新特性:SQL Plan Management(SPM)

    Oracle11g中,Oracle提供dbms_spm包来管理SQL Plan,SPM是一个预防机制,它记录并评估sql的执行计划,将已知的高效的sql执行计划建立为SQL Plan Baseline ...

  6. PLSQL_性能优化工具系列09_SQL Plan Management

    2014-09-24 Created By BaoXinjian

  7. 官方文档:11G新特性SQL PLAN BASLINE 执行计划基线

    什么是SQL执行计划管理? SQL计划管理(SQL plan management)是一咱预防机制,记录和评估SQL语句的执行计划.SQL plan management的主要功能是sql plan ...

  8. Oracle SQL操作计划基线总结(SQL Plan Baseline)

    一.基础概念 Oracle 11g開始,提供了一种新的固定运行计划的方法,即SQL plan baseline,中文名SQL运行计划基线(简称基线),能够觉得是OUTLINE(大纲)或者SQL PRO ...

  9. 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)

    基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编   ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...

随机推荐

  1. bzoj2709: [Violet 1]迷宫花园

    二分答案,spfa check就行了. gb题卡精度. #include<cstdio> #include<iostream> #include<cstring> ...

  2. 用C语言实现websocket服务器

    Websocket Echo Server Demo 背景 嵌入式设备的应用开发大都依靠C语言来完成,我去研究如何用c语言实现websocket服务器也是为了在嵌入式设备中实现一个ip camera的 ...

  3. LOJ 6089 小Y的背包计数问题 —— 前缀和优化DP

    题目:https://loj.ac/problem/6089 对于 i <= √n ,设 f[i][j] 表示前 i 种,体积为 j 的方案数,那么 f[i][j] = ∑(1 <= k ...

  4. ZOJ1450 Minimal Circle 最小圆覆盖

    ZOJ1450 给定N个点(N<=100)求最小的圆把这些点全部覆盖 考虑对于三角形,可以唯一的找到外接圆,而多边形又可以分解为三角形,所以对于多边形也可以找到唯一的最小覆盖圆. #includ ...

  5. SSM整合配置错误记录

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dic ...

  6. Android 在eclipse中没有出现AVD的解决方法(转载)

    转自:http://frabbit2013.blog.51cto.com/1067958/1243549 本文主要介绍在系统中成功配置好Android开发环境(即SDK is ok and ADT o ...

  7. E20171121-sl

    contrast  n. 对比,对照; 差异; 对照物,对立面; [摄] 反差;

  8. java 读取word

    读取word文件 import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org ...

  9. spring data elasticsearch的 @Documnet 和 @Field 注解

    @Documnet 注解 public @interface Document { String indexName(); //索引库的名称,个人建议以项目的名称命名 String type() de ...

  10. ASP.NET 知识点总结(六)

    1.传入某个属性的set方法的隐含参数的名称是什么?value,它的类型和属性所声名的类型相同. 2.如何在C#中实现继承? 在类名后加上一个冒号,再加上基类的名称.3.C#支持多重继承么? 类之间不 ...