os: centos 7.6
db: oracle 19.3
spm 的全称是 sql plan management,是 oracle 11g 中推出的一种主动稳定执行计划的手段,能够保证只有被验证过的执行计划才会被启用.
查看默认值
SQL> show parameter sql_plan;
NAME TYPE VALUE
------------------------------------ -------------------------------- ------------------------------
optimizer_capture_sql_plan_baselines boolean FALSE
optimizer_use_sql_plan_baselines boolean TRUE
当前 session 中禁掉 spm,并同时开启自动捕获 sql plan baseline
SQL> select * from dba_sql_plan_baselines;
SQL> alter session set optimizer_use_sql_plan_baselines=false;
alter session set optimizer_capture_sql_plan_baselines=true;
执行 sql
SQL> select t0.*,t1.*
from tmp_t0 t0,
tmp_t1 t1
where 1=1
and t0.id=t1.id
;
SQL> select * from dba_sql_plan_baselines;
执行第一次,在 dba_sql_plan_baselines 没有看到任何记录
再执行一次
SQL> select t0.*,t1.*
from tmp_t0 t0,
tmp_t1 t1
where 1=1
and t0.id=t1.id
;
此时查看 dba_sql_plan_baselines 时已经有了相应的结果
SQL> set pagesize 200;
set linesize 200;
col sql_handle format a30;
col plan_name format a40;
col origin format a20;
col sql_text format a80;
SQL> select sql_handle,plan_name,origin,enabled,accepted,to_char(sql_text) sql_text from dba_sql_plan_baselines;
SQL_HANDLE PLAN_NAME ORIGIN ENA ACC SQL_TEXT
------------------------------ ---------------------------------------- -------------------- --- --- --------------------------------------------------------------------------------
SQL_37a3d4db831fd717 SQL_PLAN_3g8ynvf1jzpsr9e52db30 AUTO-CAPTURE YES YES select t0.*,t1.*
from tmp_t0 t0,
tmp_t1 t1
where 1=1
and t0.id=t1.id
SQL_5c49de6d754a2305 SQL_PLAN_5skfydpunn8s56a42112a AUTO-CAPTURE YES YES select sql_handle,plan_name,origin,enabled,accepted,to_char(sql_text) from dba_s
ql_plan_baselines
SQL_9c0d7998b1d28680 SQL_PLAN_9s3btm2sx51n0c51fbe40 AUTO-CAPTURE YES YES select * from dba_sql_plan_baselines
我们只需要关注 PLAN_NAME=SQL_PLAN_3g8ynvf1jzpsr9e52db30
SQL> alter session set optimizer_use_sql_plan_baselines=true;
alter session set optimizer_capture_sql_plan_baselines=false;
新开 session,测试 spm 的效果
explain plan
for
select t0.*,t1.*
from tmp_t0 t0,
tmp_t1 t1
where 1=1
and t0.id=t1.id
;
select * from table(dbms_xplan.display())
;
Plan hash value: 3832590891
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 30 | 6 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 3 | 30 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| TMP_T0 | 3 | 18 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| TMP_T1 | 3 | 12 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T0"."ID"="T1"."ID")
Note
-----
- SQL plan baseline "SQL_PLAN_3g8ynvf1jzpsr9e52db30" used for this statement
最后一行 SQL plan baseline “SQL_PLAN_3g8ynvf1jzpsr9e52db30” used for this statement
说明 spm 已经生效了.
如果有多条相同sql baseline,可以选择具体哪条 baseline
declare
lv_tmp pls_integer;
begin
lv_tmp:= dbms_spm.alter_sql_plan_baseline(
sql_handle => 'SQL_37a3d4db831fd717',
plan_name => 'SQL_PLAN_3g8ynvf1jzpsr9e52db30',
attribute_name => 'ENABLED',
attribute_value => 'YES' -- YES NO
);
end;
参考: