sql plan management

本部分描述如何用sql plan management管理sql plan。

?  sql plan baselines概述

Oracle Database 11g引入了一个名为SQL plan Management(SPM)的新计划稳定性特性,它让数据库通过sql plan baseline

控制sql计划的演变。SPM的目的是面对数据库升级、系统和数据库更改以及应用升级和故障修复等变动时保护sql代码的性能。

?  sql Plan baselines结构

一个计划基线包含一个或者多个接受的plan,每个计划包含如下信息:

n  hit集合

n  plan hash value

n  plan 相关信息

plan history是一个计划集,包括接受的和不接受的.只有接受的plans在sql plan baseline,baseline的plan是plan history的一个子集。

?  Managing Sql Plan Baselines

?  Capturing sql plan baselines

在sql plan baseline捕获阶段,数据库探测plan 改变并记录新的plan,这样可以演变。为了这个目的,数据库为每一个sql语句维护了一个

plan history。因为特殊的sql不会重复因此不会遭受性能退化,数据库只会维护重复执行sql的plan history。

为了识别重复执行的sql语句,数据库维护一个包含优化器评估过的sql id的日志(通过trace,可以看到,应该记录到sqllog$),

当sql解析或者执行时,如果该sql已经记录了,数据库就认为这个sql是重复执行的。

每个重复执行的sql语句,数据库维护优化器产生的所有plan的一个plan history。在plan history中被接受的子集就是sql plan baseline.

在sql plan 捕获阶段,有自动捕获和手动加载两种方式。

n  自动捕获

可以通过设置OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES 为true,启用sql计划基线自动装载,如下所示:

16:20:55 sys@vposdb> alter system set optimizer_capture_sql_plan_baselines=true;

System altered.

optimizer_capture_sql_plan_baselines默认值为false,表示自动假话捕捉默认关闭。

数据库使用每条sql语句的优化程序的详细数据重新生成执行计划。每条sql语句的第一个计划被标记为供优化程序使用。此时,计划历史和sql计划基线

是相同的。优化器随后生成的sql语句的所有新计划成为计划历史的组成部分。在最后的sql计划基线计划阶段(sql plan baseline evolution)中,

数据库将对sql计划基线添加已证明不会导致性能衰退的计划。

手动sql计划装载

n  从库缓存中加载

我们可以使用dbms_spm.load_plans_from_cursor_cache来将sql计划基线手工导入数据字典。此函数重载了多次以支持不同的方法来识别哪些游标需要处理。

DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (

sql_id            IN  VARCHAR2,

plan_hash_value   IN  NUMBER   := NULL,

sql_text          IN  CLOB,

fixed             IN  VARCHAR2 := 'NO',

enabled           IN  VARCHAR2 := 'YES')

RETURN PLS_INTEGER;

DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (

sql_id            IN  VARCHAR2,

plan_hash_value   IN  NUMBER   := NULL,

sql_handle        IN  VARCHAR2,

fixed             IN  VARCHAR2 := 'NO',

enabled           IN  VARCHAR2 := 'YES')

RETURN PLS_INTEGER;

DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (

sql_id            IN  VARCHAR2,

plan_hash_value   IN  NUMBER   := NULL,

fixed             IN  VARCHAR2 := 'NO',

enabled           IN  VARCHAR2 := 'YES')

RETURN PLS_INTEGER;

DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (

attribute_name   IN VARCHAR2,

attribute_value  IN VARCHAR2,

fixed            IN VARCHAR2 := 'NO',

enabled          IN VARCHAR2 := 'YES')

RETURN PLS_INTEGER;

我们可以通过两种方式来加载。

1.         通过指定以下属性中的一个来识别一些sql语句

attribute_name

One of possible attribute names:

'SQL_TEXT' sql语句的文本内容

'PARSING_SCHEMA_NAME' 用于解析游标的schema

'MODULE'           执行了这条sql语句的模块名

'ACTION'           执行了这条语句的活动名

例子如下

DECLARE

ret PLS_INTEGER;

BEGIN

ret := dbms_spm.load_plans_from_cursor_cache(attribute_name  => 'sql_text',

attribute_value => '%/* MySqlStm */%');

dbms_output.put_line(ret || ' SQL plan baseline(s) created');

END;

/

上面pl/sql块的意思是为库缓存里每一条文本中包含字符串MySqlStm的sql语句创建一个计划基线。

2.         通过sql_id加载

通过sql_id加载比较简单,如下:

DECLARE

ret PLS_INTEGER;

BEGIN

ret := dbms_spm.load_plans_from_cursor_cache(sql_id          => '&sql_id',

plan_hash_value => NULL);

dbms_output.put_line(ret || ' SQL plan baseline(s) created');

END;

/

这里面plan_hash_value是可选的,为null意味着该sql_id的所有可用的执行计划都会被加载。

CREATE TABLE t (id, n, pad, CONSTRAINT t_pk PRIMARY KEY (id))

AS

SELECT rownum, rownum, rpad('*',500,'*')

FROM dual

CONNECT BY level <= 1000;

CREATE INDEX i ON t (n);

11:01:27 sys@vposdb> SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Elapsed: 00:00:00.02

Execution Plan

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT   |      |     1 |   505 |    21   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |   505 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |     1 |   505 |    21   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - filter("N"=42)

Statistics

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

1  recursive calls

0  db block gets

74  consistent gets

0  physical reads

0  redo size

528  bytes sent via SQL*Net to client

520  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

11:01:42 sys@vposdb> SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Elapsed: 00:00:00.01

Execution Plan

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

Plan hash value: 3694077449

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

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT             |      |     1 |   505 |     2   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE              |      |     1 |   505 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |   505 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | I    |     1 |       |     1   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

3 - access("N"=42)

Statistics

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

1  recursive calls

0  db block gets

3  consistent gets

0  physical reads

0  redo size

528  bytes sent via SQL*Net to client

520  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

0  sorts (memory)

0  sorts (disk)

1  rows processed

明显第二个执行计划比第一个效率更高。如果我们无法修改sql可以使用sql计划基线来解决这个问题

10:45:22 SQL>

ALTER SESSION SET optimizer_capture_sql_plan_baselines = TRUE;

Executed in 0 seconds

SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Executed in 0.046 seconds

SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Executed in 0.047 seconds

ALTER SESSION SET optimizer_capture_sql_plan_baselines = FALSE;

Executed in 0 seconds

13:59:08 sys@vposdb> SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Elapsed: 00:00:00.01

Execution Plan

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT   |      |     1 |   505 |    21   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |   505 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |     1 |   505 |    21   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - filter("N"=42)

Note

-----

- SQL plan baseline "SQL_PLAN_3u6sbgq7v4u8z3fdbb376" used for this statement

我们可以通过上面输出的计划名,可以通过数据字典视图dba_sql_plan_baselines找到sql计划基线的标示符:

sql句柄(handle)

14:04:55 sys@vposdb> select sql_handle

14:05:13   2  from dba_sql_plan_baselines

14:05:13   3  where plan_name='SQL_PLAN_3u6sbgq7v4u8z3fdbb376'   ;

SQL_HANDLE

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

SQL_3d1b0b7d8fb2691f

Elapsed: 00:00:00.00

14:05:14 sys@vposdb>

接下来,我们从库缓存中加载sql语句使用索引扫描的执行计划。

14:21:08 sys@vposdb> select sql_text,sql_id from v$sql where sql_text like '%/*+ index(t) */ count(pad) FROM t WHERE n = 42%' ;

SQL_TEXT

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

SQL_ID

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

SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

7jvvrqqd0xffz

explain plan for SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

4jwnyvhudy196

explain plan for SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

4jwnyvhudy196

SQL_TEXT

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

SQL_ID

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

explain plan for SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

4jwnyvhudy196

select sql_text,sql_id from v$sql where sql_text like '%/*+ index(t) */ count(pad) FROM t WHERE n = 42%'

02cnh5mgkagba

EXPLAIN PLAN SET STATEMENT_ID='PLUS4294967295' FOR SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

d6pw9fs89anwp

SQL_TEXT

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

SQL_ID

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

select sql_text,sql_id from v$sql where sql_text like '%/*+ index(t) */ count(pad) FROM t WHERE n = 42%'

bjycuvyfj2yvs

SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

dat4n4845zdxc

select * from v$sql where sql_text like '%/*+ index(t) */ count(pad) FROM t WHERE n = 42%'

3hpk25qpwmxhw

9 rows selected.

Elapsed: 00:00:00.39

14:22:09 sys@vposdb> SELECT * FROM table (

14:23:34   2     DBMS_XPLAN.DISPLAY_CURSOR('dat4n4845zdxc'));

PLAN_TABLE_OUTPUT

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

SQL_ID  dat4n4845zdxc, child number 0

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

SELECT /*+ index(t) */ count(pad) FROM t WHERE n = 42

Plan hash value: 3694077449

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

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT             |      |       |       |     2 (100)|          |

|   1 |  SORT AGGREGATE              |      |     1 |   505 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |   505 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | I    |     1 |       |     1   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

3 - access("N"=42)

20 rows selected.

Elapsed: 00:00:00.04

14:26:18 sys@vposdb> DECLARE

14:26:53   2    ret PLS_INTEGER;

14:26:53   3  BEGIN

14:26:53   4    ret := dbms_spm.load_plans_from_cursor_cache(sql_id          => 'dat4n4845zdxc',

14:26:53   5                                                 plan_hash_value => NULL,

14:26:53   6                                                 sql_handle      =>'SQL_3d1b0b7d8fb2691f');

14:26:53   7    dbms_output.put_line(ret || ' SQL plan baseline(s) created');

14:26:53   8  END;

14:26:54   9  /

1 SQL plan baseline(s) created

PL/SQL procedure successfully completed.

14:27:47 sys@vposdb> select plan_name from dba_sql_plan_baselines where sql_handle='SQL_3d1b0b7d8fb2691f';

PLAN_NAME

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

SQL_PLAN_3u6sbgq7v4u8z3fdbb376

SQL_PLAN_3u6sbgq7v4u8z59340d78

我们现在已经有两个执行计划了。我们将全表扫描的baseline删除掉。

SET SERVEROUTPUT ON

14:56:40 sys@vposdb> DECLARE

14:56:59   2     ret PLS_INTEGER;

14:56:59   3   BEGIN

14:56:59   4     ret := dbms_spm.drop_sql_plan_baseline(sql_handle =>'SQL_3d1b0b7d8fb2691f',

14:56:59   5                                            plan_name  =>'SQL_PLAN_3u6sbgq7v4u8z3fdbb376'

14:56:59   6                                            );

14:56:59   7     dbms_output.put_line(ret || ' SQL plan baseline(s) created');

14:56:59   8   END;

14:56:59   9   /

1 SQL plan baseline(s) created

PL/SQL procedure successfully completed.

接下来,我们再次执行sql看看是否选用新的计划基线。

14:58:13 sys@vposdb>  SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42;

COUNT(PAD)

----------

1

Elapsed: 00:00:00.07

Execution Plan

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

Plan hash value: 3694077449

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

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT             |      |     1 |   505 |     2   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE              |      |     1 |   505 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |   505 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | I    |     1 |       |     1   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

3 - access("N"=42)

Note

-----

- SQL plan baseline "SQL_PLAN_3u6sbgq7v4u8z59340d78" used for this statement

我们看到及时sql语句中包含提示full,执行计划也不在使用全表扫描。

此外,我们还可以检查v$sql中sql_plan_baseline列。

16:21:40 sys@vposdb> select sql_plan_baseline from v$sql where sql_id='bhk25zu92v046';

SQL_PLAN_BASELINE

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

SQL_PLAN_3u6sbgq7v4u8z3fdbb376

SQL_PLAN_3u6sbgq7v4u8z3fdbb376

?  显示sql计划基线。

当我们让sql使用了baseline后,baseline对应什么plan呢,这个是我在看到这部门内容之前,思考但是没有查找到答案的问题。

使用

SELECT * FROM table (

DBMS_XPLAN.DISPLAY_CURSOR('61p8t9216bc71',1));

并不能显示正确的执行计划,这个只是最初的执行计划,当然我们有一个方法,就是将sql_id剔出库缓存,

重新加载后,生成的执行计划为baseline之一(当一个sql有多个baseline时)。

SELECT * FROM TABLE(

DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(

sql_handle=>'SQL_3d1b0b7d8fb2691f'));

16:51:18 sys@vposdb> SELECT * FROM TABLE(

17:11:54   2      DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(

17:11:54   3          sql_handle=>'SQL_PLAN_3u6sbgq7v4u8z59340d78'));

PLAN_TABLE_OUTPUT

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

Error: specified SQL handle SQL_PLAN_3u6sbgq7v4u8z59340d78 does not exist

Elapsed: 00:00:00.02

17:11:55 sys@vposdb> SELECT * FROM TABLE(

17:12:21   2      DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(

17:12:21   3          sql_handle=>'SQL_3d1b0b7d8fb2691f'));

PLAN_TABLE_OUTPUT

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

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

SQL handle: SQL_3d1b0b7d8fb2691f

SQL text:  SELECT /*+ full(t) */ count(pad) FROM t WHERE n = 42

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

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

Plan name: SQL_PLAN_3u6sbgq7v4u8z3fdbb376         Plan id: 1071362934

Enabled: YES     Fixed: NO      Accepted: NO      Origin: AUTO-CAPTURE

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

Plan hash value: 2966233522

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

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT   |      |     1 |   505 |    21   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |   505 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |     1 |   505 |    21   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - filter("N"=42)

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

Plan name: SQL_PLAN_3u6sbgq7v4u8z59340d78         Plan id: 1496583544

Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD

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

Plan hash value: 3694077449

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

| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT             |      |     1 |   505 |     2   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE              |      |     1 |   505 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |   505 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | I    |     1 |       |     1   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

3 - access("N"=42)

46 rows selected.

Elapsed: 00:00:00.16

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29033984/viewspace-1175582/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29033984/viewspace-1175582/

11g-sql plan management相关推荐

  1. oracle spm buffer get比较过程,Oracle 11g 新特性 -- SQL Plan Management 示例

    一. SPM 说明 与Oracle 9i 的outline和10g 的profile比,Oracle 11g的SPM相对更加的灵活.如,一条带有绑定变量的SQL语句,最好的执行计划会根据绑定变量的值而 ...

  2. 11g新特性-SQL Plan Management

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

  3. 【11g】SPM说明(SQL Plan Management )

    Oracle 11g 新特性 -- SQL Plan Management 说明 2012年12月13日 20:14:45 Dave 阅读数:9173 版权声明: https://blog.csdn. ...

  4. SQL Plan Management介绍

    基于成本的优化法则基于统计信息找到最优执行计划,但是一些环境的变化可能影响执行计划的改变如: ·         New optimizer version ·         Changes to ...

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

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

  6. 【DB笔试面试609】在Oracle中,SPM(SQL Plan Management,SQL计划管理)是什么?

    ♣题目 部分 在Oracle中,SPM(SQL Plan Management,SQL计划管理)是什么? ♣答案部分 Outline的缺点是太过死板,当数据量大幅度变化时无法做出相应的改变.SQL P ...

  7. SPM(SQL Plan baseline)(11g)

    第一篇:介绍 sql plan baseline(sql计划基线)是什么? sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划 ...

  8. Oracle 12c 新特性:SQL Plan Directives与过量的动态采样解析

    在 12c 中,优化器进行了较大的改变,推出了 Adaptive query optimization,从整体上说,Adaptive query optimization 可以看作如下两部分: 一部分 ...

  9. 推荐: SQL Server Management Express Edition插件

    如果使用SQL Server2005的Express版本时,不可避免需要使用SQL Server Management  Express Edition.而2005版本之前的管理器中书写SQL.查找字 ...

最新文章

  1. Linux 虚拟化网络技术 — 物理网卡的虚拟化(MACVLAN 和 MACVTAP)
  2. 网站核心关键词一定要控制在五个之内更方便集中优化
  3. Swift 4正式发布,新功能概览
  4. 451 Research发布《2019年数据中心服务和基础设施预测》
  5. 【学习笔记】Python - NumPy
  6. npm 全局安装vuecli报错_cnn explainer本地使用--被npm坑惨
  7. mysql 重置密码 win_window下重置mysql用户密码
  8. ukey证书是什么意思_什么是证书?
  9. mysql数据库引擎问题
  10. Python基础应用-摄氏温度换算
  11. rss订阅,全文阅读,渴望大家发贴的时候在RSS中总是显示全文
  12. Android Studio升级到3.0版本后布局不能预览解决方案
  13. 今日睡眠质量记录85分
  14. python计算机视觉编程——基本的图像操作和处理
  15. 困扰成都青年的20年癫痫在三博脑科医院终结
  16. 中科大和西工大 计算机考研真题,中科大给考6系同学的一点复试建议
  17. 教师资格证考试科目汇总
  18. 安装 Electron 的门道
  19. linux电子词典项目流程,毕业设计_linux下电子词典的设计与实现.doc
  20. Substance Painter 的一些玩法笔记

热门文章

  1. 电脑计算机网络都打不开怎么办,电脑打不开网页怎么办?如何解决电脑网页打不开问题...
  2. 期末复习系列之企业管理
  3. matlab中图像分割技术之二阈值分割
  4. 张量基础学习 (三 张量代数运算———上)
  5. winArpAttacker使用问题
  6. LeetCode刷题记录02——新手村专辑(一)
  7. EasyX接收并显示从控制台输入的数字和英文
  8. Work20230506
  9. 手机浏览器微信h5支付
  10. 制作操作系统启动U盘