SPM(SQL Plan baseline)(11g)



第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。





















第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。
























第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。























第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。





















第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。





















第一篇:介绍
sql plan baseline(sql计划基线)是什么?
sql plan baseline是一个与sql语句相关联的对象,它被设计用来影响query optimizer产生执行计划时的决定。是stored outline的改进版本,可以在不修改语句的情况下调优sql语句。

怎么才能让query optimizer用 用sql plan baseline来生成执行计划了 
show parameter optimizer_use_sql_plan_baselines
alter system set optimizer_use_sql_plan_baselines=false;
alter system set optimizer_use_sql_plan_baselines=true;
参数true才可以。
默认也为true,可以在session与system级别设置。

Query optimizer在有了sql plan baseline后的选择逻辑:
一个sql提交到query optimizer,首先产生一个执行计划。然后对sql语句进行标准化,使其不区分大小写与空格的影响,再做hash算法取得签名,去比对数据字典中是否有关于这个sql的已存在的并且可接受的sql plan bashline(其中包含一堆hint),如果没发现就照传统那样执行sql。如果有就再检测sql语句与基线中的sql语句是否一致(不检测的话有可能发生哈希冲突,即不同的sql文本指向一样的签名),如果没冲突,就会选择sql plan baseline中代价最小的那个执行,如果有冲突就照传统那样执行。

贴图:


第二篇:从视图与字段获取信息:
对于执行计划来说,在v$sql中是plan_hash_value标识,而加载到sql plan baseline中就是plan_name来标识了。
对于sql,v$sql中是sql_id标识,加载进baseline后就是用sql_handle标识了。
正如sql_id对应多个child_number,即有多个不同执行环境下的plan_hashh_value,所以对sql_handle,也有多个plan_name对应的执行计划,很可能每个代价不一样。
sql计划基线,sql plan baseline是由两个字段标识的,sql_handle与Plan_name

--DBA_SQL_PLAN_BASELINES
select SQL_HANDLE,SQL_TEXT,PLAN_NAME,origin,CREATED,ENABLED,ACCEPTED,fixed,AUTOPURGE,EXECUTIONS,buffer_gets
  from DBA_SQL_PLAN_BASELINES
where sql_text like '%&sqltext%';
--where plan_name='&planname';
--where sql_handle='&handle';

字段的说明

sql_handle:表示SQL语句的句柄

plan_name: 表示该SQL语句执行计划的名字

origin: 表示该执行计划是如何进入plan history的。AUTO-CAPTURE:优化器自动加入;MANUAL:DBA手工加入

enabled: 表示是否被启用了。YES(默认):启用 NO:禁用。如果某个执行计划为禁用,则优化器根本就不会考虑使用该执行计划

accepted: 表示是否接受,也就是是否进入了plan baseline里,YES表示接受,NO表示不接受

autopurge: 表示是否为定期自动删除,YES表示是,NO表示否。

fixed: 当plan baseline中有多个执行计划时,表示优化器仅考虑这些被设置为FIXED的计划,从中选择一个最优的。


--执行完SQL以后,也可以从v$sql视图的sql_plan_baseline中反映是否用了baseline,以及用了哪个plan_name。
select sql_plan_baseline
  from v$sql
 where sql_plan_baseline is not null
   and last_load_time > sysdate - 1 / 24;

--显示某个sql_handle的 的多个执行计划
   select *
     from table(dbms_xplan.display_sql_plan_baseline(sql_handle => 'SQL_63dc5da680b1078f'));

--查看某个plan_name包含的hint,要用这个非正式方法来将xml转换到可读的输出哦。
select extractvalue(value(h),'.') as hint
from sys.sqlobj$data od,sys.sqlobj$ so,
table (xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
where so.name='SQL_PLAN_67r2xnu0b21wgc1bea826'
and so.signature=od.signature
and so.category=od.category
and so.obj_type=od.obj_type
and so.plan_id=od.plan_id;

--查看retention period,一般为53周
select parameter_value from dba_sql_management_config where parameter_name='PLAN_RETENTION_WEEKS';

第二篇:怎么捕获SQL计划基线?
1.自动捕获sql plan baseline,重复执行过(至少执行两次)的sql,会存储一个新的sql plan baseline。
alter session set optimizer_capture_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
alter system set optimizer_capture_sql_plan_baselines=true;
alter system set optimizer_capture_sql_plan_baselines=false;

PA:可能因为会引起额外负载,所有自动捕获都关了。
生产:11g false
测试:11g false

贴图:

提示:自动捕获完后,关闭参数了,但是后期有关于这个sql的新的执行计划,也会被加载到sql计划基线中,也算是AUTO-CAPTURE。
证明.txt
而恰恰,手工加载的,加载完了再有相同的sql进来,就算这个SQL有更好的执行计划,也不会被加载了,而且会受baseline的影响而沿用baseline的执行计划,那怕baseline的执行计划更差。
证明.txt


一个sql_handle第一个plan_name的accepted是接受的,但第二个plan_name进来就是不可接受的,可以有多个可以接受的,query optimizer会考虑选择一个。手工加载的都是可接受的,自动加载的第二个起就是不可接受的。
证明.txt

2.从库缓存加载

--为library cache中每一条文本中包含字符串MySqltm的SQL语句创建一个SQL计划基线:
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'sql_text',
attribute_value=>'%MySqlStm%');
end;
/
--为某个用户的游标创建基线
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
attribute_name=>'parsing_schema_name',
attribute_value=>'SCOTT');
end;
/
--通过SQL_id手工创建
--如果执行计划的哈希值没有指定或指定为NULL,则给定SQL语句的所有可用执行计划都会被加载。
declare
ret  varchar2(100);
begin
ret := dbms_spm.load_plans_from_cursor_cache(
sql_id=>'fwjgwwp18z7ad',
--plan_hash_value=>'1601196873'
plan_hash_value=>NULL
);
end;
/

第三篇:修改sql plan baseline
--对某个已存在的sql_handle,再手动加载新的执行计划
为某个sql_handle,从库缓存中加载执行计划与性能信息,null的话会加载该sql_id对应的不同执行计划都会被加载。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(
sql_handle=>'SQL_63dc5da680b1078f',
sql_id=>'2y5r75r8y3sj0',
--plan_hash_value=>'3694077449',
plan_hash_value=>NULL
);
end;
/

对某个sql_handle,移除某个执行计划。
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f',
plan_name=>'SQL_PLAN_67r2xnu0b21wg94ecae5c'
);
end;
/

更改sql plan baseline中的属性
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_e436abaac44f99d8',
plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
attribute_name=>'fixed',
attribute_value=>'yes'
);
end;
/

sql_handle与plan_name至少指定一个,如果只指定sql_handle,则该sql_handle对应的多个plan_name都会受更改。如果只指定Plan_name应该是可以的,因为很少有相同plan_name的不同sql_handle吧,除非人为指定plan_name.

attribute_name与attribute_value可以选择:
enabled=yes(默认)|no,只有设置yes,才有了让查询优化器使用的基本条件,当然,后续查优还考虑是否accepted。
fixed=yes|no(默认),yes的话这个sql_handle就不再吸纳新的plan_name了,而且sql plan base其余未accepted的也将不能被演化,如果有若干个accepted的,fixed的也要比nonfixed的优先级高。
证明fixed是yes后不能被演化.txt
autopurge=yes(默认)|no,yes的话保留期内没有被使用过,并且fixed不是yes,就会被自动移除。
plan_name='更改plan_name为abc,自定义30字节字符串'
description='500字节描述这个sql plan baseline'

--修改retention period,修改成12周,如果值为NULL则恢复默认值。
exec dbms_spm.configure(parameter_name=>'plan_retention_weeks',parameter_value=>12);

第四篇:演化   演化就是将未accept的变为accept的。
--当query optimizer发现有一个与通过sql plan baseline强制产生的执行计划不同的更高效的执行计划存在时,就会自动创建一个新的不可接受状态的sql plan baseline,query optimizer不能立即使用它,它在等待着演化进行。
--当演化进行时,query optimizer以不同的执行计划执行这条语句,比较性能,如果性能确实更高,这个不可接受状态的sql plan baseline就会被接受。
select dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_63dc5da680b1078f'
--plan_name=>NULL,
--time_limit=>10,
--verify=>'yes',
--commit=>'yes'
)
from dual;
sql_handle默认是NULL
plan_name不指定的话默认就是NULL,此时会演化这个sql_handle对应的所有未接受的plan_name。
time_limit=>DBMS_SPM.AUTO_LIMIT(默认),单位分钟。
verify默认yes,选择no则无需验证,直接接受该sql计划基线。
commit,默认yes,数据字典将按照演化的结果进行修改,如果为no,假设verify是yes,则只验证而不修改数据字典。



第五篇:移动sql计划基线

首先创建舞台表
dbms_spm.create_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
tablespace_name=>'USERS'
);

将sql plan baseline从数据字典复制到舞台表
declare
v_ret  number(100);
begin
v_ret := dbms_spm.pack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_handle=>'SQL_e436abaac44f99d8',
--plan_name=>'SQL_PLAN_f8dpbpb24z6fs94ecae5c',
);
end;
/

用expdp\impdp或exp,imp工具从测试库将表移到生产库

将sql plan baseline从舞台表复制到数据字典
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
table_name =>'mystgtab',
table_owner=>user,
sql_text=>'%FROM t%'
);
end;
/

对于pack_stgtab_baseline与unpack_stgtab_baseline的选项:
如果只指定table_name与table_owner,就是处理所有sql plan baseline。
sql_handle与plan_name一起能精确识别一个sql plan baseline,plan_name为可选项。
sql_text里面区分大小写

第六篇:删除sql计划基线
declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.unpack_stgtab_baseline(
sql_handle=>'mystgtab',
plan_name=>'swew223'
);
end;
/
这两个参数至少要指定一个。





















你可能感兴趣的:(性能调优,统计信息,执行计划)