这种方法只适合sql本身有更好的执行计划,不能绑定自己构造的执行计划(比如加hint)
找到慢sql的sql_id
查看某条sql各种执行计划信息
由sql_id来找,可用v$active_session_history,不过dba_hist_active_sess_history可找的时间范围较长
select SQL_PLAN_HASH_VALUE,round(avg(RUN_MINS),2) as avg_run_mins,count(*) from
(
SELECT T.SQL_ID, T.SQL_EXEC_ID,
CAST(MAX(T.SAMPLE_TIME) AS DATE) EXEC_END_TIME,
T.SQL_EXEC_START EXEC_START_TIME,
ROUND((CAST(MAX(T.SAMPLE_TIME) AS DATE) - T.SQL_EXEC_START) * 1440, 2) RUN_MINS,
T.SQL_PLAN_HASH_VALUE, T.MODULE
FROM dba_hist_active_sess_history T
WHERE T.SQL_ID = '5w91hk4nmcmrx'
AND T.SAMPLE_TIME > SYSDATE - 36
GROUP BY T.SQL_ID, T.SQL_EXEC_ID, T.SQL_EXEC_START, T.SQL_PLAN_HASH_VALUE, T.MODULE
ORDER BY EXEC_END_TIME DESC
)
group by SQL_PLAN_HASH_VALUE
order by 2 desc;
查询所需执行计划是否在缓存中,如果在,直接从缓存载入更为简单
select sql_text,
sql_id,
hash_value,
child_number,
plan_hash_value,
to_char(LAST_ACTIVE_TIME, 'hh24:mi:ss') time
from v$sql a
where sql_id='26kqp5puukbh8' and plan_hash_value='3059001790'
从库缓存中载入(时间太久可能已不在缓存中)
DECLARE
l_plans_loaded PLS_INTEGER;
BEGIN
l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '5w91hk4nmcmrx',plan_hash_value=> '3570344087');
END;
/
或者利用sqlset从AWR中载入
查看期望的执行计划产生的时间
select * from dba_hist_sql_plan where sql_id='26kqp5puukbh8' and plan_hash_value='3059001790' order by timestamp desc;
-- 2018/2/28 17:32:03
根据产生时间找到对应的快照ID
select * from dba_hist_ash_snapshot d where d.BEGIN_INTERVAL_TIME like '28-FEB-18%' order by d.BEGIN_INTERVAL_TIME;
--24257 24258
--查看数据库中已有dba_sqlset
select owner, name, id, created, statement_count from dba_sqlset order by created;
--创建sqlset
begin
DBMS_SQLTUNE.CREATE_SQLSET('mysts180104','SQL Tuning Set for loading plan into SQL Plan Baseline');
end;
/
--load sqlset
-- load之前先检查一下sqlset的情况,我们看到,load之前,是空。
SELECT first_load_time,
executions as execs,
parsing_schema_name,
elapsed_time / 1000000 as elapsed_time_secs,
cpu_time / 1000000 as cpu_time_secs,
buffer_gets,
disk_reads,
direct_writes,
rows_processed,
fetches,
optimizer_cost,
sql_plan,
plan_hash_value,
sql_id,
sql_text
FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(sqlset_name => 'mysts180306'));
--利用快照从awr中load
DECLARE
cur sys_refcursor;
BEGIN
OPEN cur FOR
SELECT VALUE(P)
FROM TABLE(
dbms_sqltune.select_workload_repository
(begin_snap=>24257, --老执行计划起始的snap id
end_snap=>24258, --老执行计划结束的snap id
basic_filter=>'sql_id = ''26kqp5puukbh8''', --老执行计划起始的sql id
attribute_list=>'ALL')
) p;
DBMS_SQLTUNE.LOAD_SQLSET( sqlset_name=> 'mysts180306', populate_cursor=>cur);
CLOSE cur;
END;
load 完之后,再次检查sqlnet情况,发现已经存在
--查看sqlset中的执行计划
set long 999999999
set line 1000
set pages 1000
SELECT * FROM table (DBMS_XPLAN.DISPLAY_SQLSET('mysts180306','26kqp5puukbh8'));
可以看到其中的Plan hash value值
Plan hash value: 1734317001
...
Plan hash value: 2335232284
...
Plan hash value: 3059001790
--查看原本基线信息
SELECT * FROM dba_sql_plan_baselines;
--从SQL调优集合中载入基线
DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(
sqlset_name => 'mysts180306',
basic_filter=>'plan_hash_value = ''3059001790'''
);
END;
检查创建后信息
SELECT * FROM dba_sql_plan_baselines where origin='MANUAL-LOAD' order by created desc;
将该基线转为fixed
DECLARE
i NATURAL;
BEGIN
i := dbms_spm.alter_sql_plan_baseline(
'SQL_3ebb770da822a759',
'SQL_PLAN_3xfvr1qn259ut58e43372',
attribute_name => 'FIXED',
attribute_value => 'YES');
dbms_output.put_line(i);
END;
SELECT * FROM dba_sql_plan_baselines where origin='MANUAL-LOAD' order by created desc;
查看基线中的执行计划
select * from table(dbms_xplan.display_sql_plan_baseline('SQL_3ebb770da822a759', plan_name => 'SQL_PLAN_3xfvr1qn259ut58e43372',format => 'ADVANCED'));
可以看到
Plan name: SQL_PLAN_3xfvr1qn259ut58e43372 Plan id: 1491350386
Enabled: YES Fixed: YES Accepted: YES Origin: MANUAL-LOAD