oracle SQL计划管理 2

2023年 12月 7日 25.5k 0

1.1.1.1   捕获SQL计划基线

可以通过几个步骤来捕获新的SQL计划基线。基本上,它们是由数据库引擎自动创建的,或由数据库管理员或开发人员手动创建。下面三部分分别介绍了三种方法。

 

Ø  自动捕获

将初始化参数optimizer_capture_sql_plan_baselines设置为TRUE时,查询优化器会自动保存新的SQL计划基线。默认情况下,会将初始化参数设置为FALSE。可以在会话和系统级别更改它。

 

启用自动捕获时,查询优化会为每条多次执行(即至少执行两次)的SQL语句保存新的SQL计划基线。为此,它会在SQL基础管理平台中管理一个日志来插入每条它处理的SQL语句签名。这代表某一SQL语句第一次执行后,它的签名仅会插入日志。然后,当同一个SQL语句第二次执行时,会创建仅包含当前执行计划的SQL计划基线并且标记为接受。从第三次执行开始,由于SQL计划基线已经与SQL语句相关联,因此查询优化器还会比较当前执行计划与SQL计划基线生成的执行计划。

 

如果它们不匹配,这代表根据当前查询优化器的估算,最优的执行计划并不是存储在SQL计划基线中的那个。为了保存这个信息,会将当前执行计划添加到SQL计划基线中并且标记为不接受。然而,就像你之前看到的那样,当前执行计划无法使用。会强制查询优化器使用SQL计划基线生成的执行计划。图11-9总结了整个处理过程。

 

图11-9 自动捕获SQL计划基线期间执行的主要步骤

将某个新的执行计划存储到SQL计划基线中时,重点需要区分以下两种情况。

Ø  如果这是SQL计划基线的第一个执行计划,则会将执行计划存储为接受,因此,查询优化器将能够使用它。

Ø  如果这不是SQL计划基线的第一个执行计划,则会将它存储为不接受,因此,查询优化器无法使用它。“进化SQL计划基线”部分将介绍如何使SQL计划基线生效,以使其对查优化器可用。

 

Ø  从库缓存中加载

要基于存储在库缓存中的游标手动将SQL计划基线加载进数据字典中,可以使用dbms_spm包下的load_plans_from_cursor_cache函数。

 

实际上,会多次重载函数来支持确定必须处理哪些游标的不同方法。这包含两种主要的可能。第一,通过指定以下属性之一来标识多个SQL语句。

Ø  sql_text:SQL语句的文本。这个属性支持通配符(例如%)。

Ø  parsing_schema_name:用来解析游标的模式名称。

Ø  module:执行SQL语句的模块名称。

Ø  action:执行SQL语句的动作名称。

 

举例说明,下面的调用引用自baseline_from_sqlarea1.sql脚本,为存储在库缓存中包含注释MysqlStm字符串的每个SQL语句创建SQL计划基线:

ret:=
dbms_spm.load_plans_from_cursor_cache(attribute_name
=>'sql_text',attribute_value =>'%/* MysqlStm */%');

 

第二,通过它的SQLID来标识SQL语句,以及可选执行计划的散列值。如果散列值没有指定或设置为NULL,所有对指定SQL语句可用的执行计划都会被加载。下面的调用,引用自baseline_from_sqlarea2.sq1脚本:

ret :=
dbms_spm.load_plans_from_cursor_cache(sql_id=>'2y5r75r8y3sjo',plan_hash_value=>NULL);

 

使用这些函数加载的执行计划会被存储为可接受,因此查询优化器可以立即利用它们。

 

在之前的例子中,SQL计划基线基于库缓存中找到的SQL语句的文本。这只有在你想确保当前的执行计划未来也会被用到时才有关系。有时,使用SQL计划基线的目的是优化SQL语句而不用修改应用。让我们看这样一个基于baseline_from_sqlarea3.sql脚本的例子。

 

假设应用执行以下SQL语句。查询优化器基于全表扫描生成执行计划。这是因为在SQL语句中包含一个hint,该hint强制查询优化器指向此操作:

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

select * from
table(dbms_xplan.display_cursor);

 

你会注意到限制列(n)上有索引存在。接着你或许想知道当使用索引时性能会怎样。因此,正如下面的例子所示,使用某个hint来执行SQL语句,以确保能够使用索引:

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

select * from table(dbms_xplan.display_cursor);

 

如果第二个执行计划比第一个更有效率,你的目的就是让应用使用它。如果无法更改应用来删除或者修改hint,可以利用SQL计划基线来解决这个问题。可以自动或者手动创建SQL计划基线来达到目的。在这种情况下,你决定使用初始化参数optimizer_capture_sql_plan_baselines:

ALTER SESSION SET
optimizer_capture_sql_plan_baselines = TRUE;

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

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

ALTER SESSION SET
optimizer_capture_sql_plan_baselines = FALSE;

 

一旦SQL计划基线创建好,就要检查是否真的使用了它。通过dbms_xplan包可以看到SQL计划名,用来标识生成执行计划的SQL计划基线:

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

select * from
table(dbms_xplan.display_cursor);

 

Note

- sql plan baseline SQL_PLAN_3u6sbgq7v4u8z3fdbb376
used for this statement

接着,基于之前的输出提供的SQL计划名,通过dba_sql_plan_baselines视图,可以找到SQL计划基线的标识符,即SQL句柄 (SQL handle):

select sql_handle FROM
dba_sql_plan_baselines WHERE plan_name='SQL_PLAN_3u6sbgq7v4u8z3fdbb376';

 

最后,你使用SQL计划基线替换执行计划。要这么做,需要加载执行索引扫描的执行计划,并移除执行全表扫描的执行计划。前者被SQL标识符以及执行计划散列值引用,后者被SQL句柄和SQL计划名引用:

ret :=
dbms_spm.load_plans_from_cursor_cache(

sql_handle =>'SQL_3d1b0b7d8fb2691f',

sql_id =>'dat4n4845zdxc',

plan_hash_value =>'3694077449');

 

ret := dbms_spm.drop_sql_plan_baseline(

sql_handle=>'SQL_3d1b0b7d8fb2691f',

plan_name
=>'SQL_PLAN_3u6sbgq7v4u8z3fdbb376');

 

要检查替换是否成功,可以测试新的SQL计划基线。请注意即使SQL语句包含full hint,执行计划也不会再使用全表扫描。

 

注意 在实践中,不恰当的hint经常导致低效的执行计划。能够使用这部分技术来覆盖它们是非常有用的。

 

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

select * from
table(dbms_xplan.display_cursor);

 

Note

- sql plan baseline
SQL_PLAN_3u6sbgq7v4u8z59340d78 used for this statement

 

要想知道SQL计划基线是否被用于某条SQL语句,也可以查询v$sql视图的sql_plan_baseline列。请注意该列显示的是SQL计划名,不是dbms_xplan包显示的SQL句柄。

 

Ø  从SQL调优集中加载

dbms_spm包下的load_plans_from_sqlset函数,可以从SQL调优集中加载SQL计划基线。加载仅需要指定所有者(owner)和SQL调优集名称。下面的调用,节选自baseline_from_sqlset.sql脚本:

ret :=
dbms_spm.load_plans_from_sqlset(sqlset_name=>'test_sqlset',sqlset_owner=>user);

 

使用该函数加载的执行计划会被存储为可接受。因此,查询优化器可以立即利用它们。

 

升级到新版本可以用到该函数。实际上,10.2版本的数据库创建的SQL调优集也可以加载到11.2版本的数据库中。Baseline_upgrade_10g.sq1和baseline_upgrade_11g.sql脚本列举了这样的应用。

 

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论