要使用公共存储概要,需要通过设置参数 USE_STORED_OUTLINES 来激活某一类存储概要;要 是有私有存储概要,则需要设置参数 USE_PRIVATE_OUTLINES。参数值为 DEFAULT 或者 TRUE 时,激活默认存储概要分类;为有效字符串时,为激活同名存储概要分类(此时,如果优化器在指定分类中找不到语句的存储概要,则从默认存储概要中查找);为 FALSE 时,关闭存储概要。要注意是, 这两个参数都不是初始化参数,无法被设置在初始化文件当中,因此需要用户显式的修改该参数值来激活存储概要。
记住,一旦当前激活的存储概要分类被修改,会话中的所有 SQL 语句,无论是否存在存储概要, 都会被优化器解析。相应的,我们可以从视图 v$sql_shared_cursor 中看到被重新解析的游标的标识字段 OUTLINE_MISMATCH 为 Y。
例如,以下的目标语句在缓存中已经有相应的子游标数据(包含执行计划)。当我们激活一个存储概要分类后,尽管该语句在此分类当中不存在存储概要,但是仍然被硬解析、生成了新的子游标:
8.2 SQL 执行计划管理
SQL 执行计划管理(SQL Plan Management,SPM)是 Oracle 11g 新引入的一个新的特性。该特性可以为 SQL 语句收集、创建一套包含多个执行计划的执行计划基线(Plan Baseline),使得 SQL 引擎在编译语句时,能让优化器总是选择代价最小的执行计划。该特性仅包含在企业版当中。SQL 执行计划管理的最重要目的是在 SQL 的执行计划解析环境发生变化时,保证 SQL 的运行性能不受影响。即,当解析环境发生变化时,优化器可能改变语句的执行计划,而 SQL 执行计划管理可以确保
SQL 执行引擎使用执行计划基线(及新解析的执行计划)当中性能最好的执行计划。
SQL 执行计划管理包含了管理工具包 DBMS_SPM、优化器中的 SPM 组件以及相关的数据字典
(也称为 SQL 管理基础,SQL Management Base,SMB,这是多个 SQL 管理工具共用的一套字典)。实际上,执行计划管理的相关信息不仅存储在物理数据字典当中,也有部分信息会存储在 Library
Cache 的数据结构当中,例如缓存的 SQL 子游标在执行计划基线的计划名称。
8.2.1 创建和增加执行计划基线
要启用执行计划管理,必须首先创建相应 SQL 的执行计划基线。而执行计划基线实际上就是一到多个执行计划以及相关性能数据。因此,创建执行计划基线,就是将 SQL 的一到多个执行计划存储到执行计划管理的数据字典当中去。执行计划管理提供了五种方法从各种来源自动或手动捕捉、 收集执行计划到计划基线当中:
• AUTO-CAPTURE:自动捕捉 SQL 语句的执行计划;
• AUTO-SQLTUNE:SQL 调优建议器(SQL Tuning Advisor)自动将调优后生成的执行计划加入计划基线当中;
• MANUAL-LOAD:手动从当前 SQL 游标缓存(Library Cache)和 SQL 调优集当(SQL Set)中加载执行计划到计划基线当中;
• MANUAL-SQLTUNE:通过 SQL 调优建议其手动创建计划基线当;
• STORED-OUTLINE:手动从从 SQL 存储概要(Stored Outlines)生成并导入执行计划到计划基线当中;
确切的说,在数据字典当中,并不是存储了语句的执行计划,而是存储了生成该执行计划所必 需的一些数据,例如 SQL 提示、绑定变量数据等。
数据字典中存储的执行计划,存在多个属性:是否已激活(Enabled),是否被接受(Accepted) 和是否被固定(Fixed)。被接受的执行计划属于进化基线;未被接受的执行计划仅作为历史数据存 在数据字典当中,需要被进化(Evovle)和验证(Verify)后才能成为基线数据。未被激活的执行计 划则不能被进化;优化器中 SPM 在选择执行计划时,仅考虑哪些已经被 SPM 接受的执行计划;而
如果基线当中存在已固定的执行计划,即使非固定的执行计划性能数据优于固定的执行计划,SPM 会优先选择已固定的执行计划。
自动捕捉加入基线的首个执行计划默认都是激活的、被接受的、但未被固定的,后面被捕捉加入的执行计划则是未被接受的,属于历史数据,需要人工对其验证、进化;如果基线当中存在已固 定的执行计划,则不会自动增加执行计划。手动加入的执行计划默认都是激活的、被接受的,但
DBMS_SPM 提供的相关函数允许在手工调用时设置是否激活和是否被固定的属性。下面分别简要的介绍这几种方法。
自动捕捉执行计划
自动捕捉的执行计划来源有两处:未创建计划基线的 SQL 语句需要启用执行计划自动捕捉功能
(将参数 optimizer_capture_sql_plan_baselines 设置为 TRUE,其默认值为 FALSE,可以在系统和会话基本设置)。然而,当开启了自动捕捉执行计划后,Oracle 并不是捕捉所有运行了的 SQL 语句的执行计划,而是仅捕捉那些被重复执行的语句;在未启用执行计划自动捕捉,且计划基线已经存在 时,如果当前缓存中不存在该语句的执行计划,优化器需要解析语句、生成执行计划,而如果新生 成的执行计划不存在语句的执行计划基线当中,则会将其加入基线。
在启用了执行计划自动捕捉,SPM 探测到还未创建执行计划基线的 SQL 执行时,
• SPM 会检查语句是否已经记录在历史日志(sqllog$)中;
o 如果不在日志当中,视其为第一次执行,并在日志中添加一条记录,但并不立即创建 其执行计划基线;
o 如果在日志当中存在其记录,视其为重复执行语句,
如果缓存中存在已经解析的执行计划,则将缓存中的执行计划存储到数据字典当 中;
如果缓存中不存在已经解析的执行计划,则解析执行计划后存储到数据字典当中;
注意,在启用了自动捕捉执行计划后,如果 SQL 语句还未创建执行计划基线,即使该语句已经被解析、缓存中存在其执行计划,优化器还是会重新解析其执行计划。
我们通过以下示例来分析 SPM 自动捕捉、创建执行计划基线的过程,为了分析其实现机制,我们在演示过程中启用了对优化器和 SQL(目的是找出 SPM 造成的递归调用语句)的跟踪。
从 SQL 存储概要中并导入执行计划
我们知道,存储概要中存储的是影响优化器生成执行计划的一组提示。在 11g 当中,执行计划基线更为灵活和稳定,因此 Oracle 推荐用户使用 SPM(这两个特性可以并存,但存储概要对优化
器的影响的优先级高于执行计划基线)。并且,SPM 工具包 DBMS_SPM 中也提供了一组接口给用户,将存储概要数据迁移到执行计划基线数据中。
下面例子当中,我们将指定目录下存储概要数据迁移到了执行计划基线当中: