技术开发 频道

点评Oracle 11g新特性之执行计划管理

    【IT168技术文档】摘要:本文描述了11g的新特性之一:执行计划管理,介绍了引入该新特性的原因,以及该新特性的相关特点、工作原理等。最后通过引入一个测试案例来介绍如何使用该新特性。

1. 执行计划管理的工作原理
    我们知道,SQL语句的性能很大程度上依赖于SQL语句的执行计划。如果SQL语句的执行计划发生改变,则SQL的性能很有可能发生大的变化。而SQL执行计划发生变化的原因有很多种,包括优化器版本的变化、统计信息的变化、优化器相关的各种参数的变化、添加或删除了索引、添加或删除了物化视图、修改了系统设置、以及是否应用了10g引入的SQL profile等。

    在11g之前,我们可以使用存储大纲(stored outline)和SQL Profile来帮助我们固定某条SQL语句的执行计划,防止由于执行计划发生变化而导致的性能下降。不过这些技术需要DBA人为的处理,比如存储大纲,需要DBA手工创建,而SQL Profile来说,则要DBA手工应用才能生效。

    从11g开始,oracle引入了SQL执行计划管理(SQL Plan Management)这个新特性,从而可以让系统自动的来控制SQL语句执行计划的稳定性,进而防止由于执行计划发生变化而导致的性能下降。

    通过启用该特性,某条语句如果产生了一个新的执行计划,只有在它的性能比原来的执行计划好的情况下,才会被使用。
为了实现执行计划管理,优化器会为所有执行次数超过一次的SQL语句维护该SQL语句的每个执行计划的历史列表(plan history)。优化器通过维护一个语句执行的日志条目(statement log)来识别该SQL语句是否为第二次执行。一旦优化器认出某条SQL语句为第二次执行,则优化器将该语句所生成的所有不同的执行计划插入到plan history的相关表里,而plan history里包含了优化器能够用于重新生成执行计划的所有信息,这些信息包括SQL文本、存储大纲、绑定变量以及解析环境(比如optimizer_mode之类影响优化器解析SQL语句的参数)等。

    当然,11g也支持手工维护SQL语句的plan history,作为对自动维护plan history的功能补充。
但是并不是说plan history里任何的执行计划都可以拿来使用。这里需要先介绍一下所谓的执行计划基准线(plan baseline)这个概念。plan baseline是plan history的一个子集,plan baseline里面的执行计划是用来比较性能好坏的一个依据。也就是说,凭什么来判断是否可以使用一个新产生的执行计划呢?就是把该新的执行计划与plan baseline里的计划进行比较来判断。某个SQL语句的执行计划可以属于plan history,但是不一定属于plan baseline。

注意:每个SQL语句都会有它自己的执行计划历史以及执行计划基准线。

那么某个SQL语句的执行计划是如何进入执行计划历史,乃至执行计划基准线的呢?
有两种方法可以将SQL语句的执行计划纳入到执行计划管理体系中去:
1) 将初始化参数:OPTIMIZER_CAPTURE_PLAN_BASELINES设置为true,则会自动的捕获SQL的执行计划。该参数缺省为false。设置为true以后,当某条SQL语句第一次执行时,该SQL语句的plan history是空的,显然该SQL语句的plan baseline也是空的。那么当该SQL第二次再次执行时,优化器会自动将该SQL语句以及相关的执行计划放入plan history,同时也会放入到plan baseline里。这就构成了最初的plan baseline,也就是说最初进入plan history的执行计划会直接自动进入plan baseline里。那么当你做了某些修改,比如添加了一个索引等,然后第三次执行该同样的SQL语句,则会产生另外一个不同的执行计划,这时新的执行计划会自动进入plan history,但是不会自动进入plan baseline。是否使用该新的执行计划,则要把该新的执行计划与plan baseline里现存的第二次执行SQL时的执行计划进行比较,如果新的执行计划成本更低,则会使用新的执行计划,否则使用plan baseline里的执行计划。

2) 使用dbms_spm包手工处理,这可以让你手工管理SQL plan baseline。使用该包,你可以直接将SQL的执行计划从shared pool里加载到plan baseline里,也可以使用dbms_spm包将已经存在的SQL Tuning Set加载到plan baseline里。同时,dbms_spm可以让你把plan history里的执行计划加入到plan baseline里。反之,你也可以使用该包将plan baseline里的执行计划移出去。

   注意,某条SQL语句的plan baseline里的第一个执行计划可以像上面说的通过设置初始化参数来自动加入,但是如果你希望在plan baseline里添加该SQL语句的其他新的执行计划时,则必须使用dbms_spm包手动完成。

那么plan baseline里的执行计划是如何被使用的呢?
    Oracle提供了一个初始化参数:OPTIMIZER_USE_PLAN_BASELINES,该参数缺省为true,表示要求优化器考
虑使用plan baseline里的执行计划,如果设置为false,则不使用执行计划管理的特性,而又回到了11g之前的状况。
以下描述基于的前提是plan baseline里已经存在了一个SQL的执行计划。

    每次优化器解析SQL语句的时候,首先仍然使用11g之前的传统方式产生一个成本最低的执行计划,然后看初始化参数:OPTIMIZER_USE_PLAN_BASELINES是否设置为true,如果为false,则直接返回所生成的执行计划。否则如果为ture,则去plan history里找是否存在相同的执行计划,如果找到了,则再去plan baseline里找是否存在相同的执行计划,如果也找到了,则直接返回该执行计划。如果在plan history里没找到相同的执行计划,则将产生的执行计划加入到plan history里,然后将执行计划与plan baseline里已经存在的执行计划进行比较,看哪个执行计划的成本低就取哪个执行计划。

    如果你为某个SQL语句保存了存储大纲,则为了向下兼容,该语句会使用存储大纲。另外,即使你通过设置初始化参数:OPTIMIZER_CAPTURE_PLAN_BASELINES为true来启动自动捕获执行计划到plan baseline里,对于使用存储大纲所生成的执行计划也不会放入plan baseline里。

    SQL语句的plan history以及plan baseline所涉及到的表是存放在SQL Management Base (SMB)里的,SMB里同样也存放了SQL Profiles。而SMB是数据字典的一部分,存放在SYSAUX表空间里。SMB所占用的空间会自动定期的删除。
0
相关文章