How to force accept a SQL Plan Baseline?

折月煮酒 提交于 2019-12-24 07:23:07

问题


In Oracle (looking at this in Oracle Enterprise Manager) I have a particular SQL Plan Baseline which is set to Enabled = YES.

However, I can't get the ACCEPTED = YES to work. According to the documentation, you need ENABLED and ACCEPTED both.

I tried to "evolve" the Baseline but OEM complains (via a Report) that it's 1.06 times worse. That's not true though.

Also I would like to know how to ensure it does not auto-purge over time and that's it's fixed. Thanks!


回答1:


To enable baseline usage, optimizer_use_sql_plan_baselines must be true.

SELECT * FROM dba_sql_plan_baselines

Consider a baseline for the plan with the lowest cost or best elapsed time. The optimizer will choose the lowest cost accepted plan but will give preference to a fixed plan. This is the best way to guarantee the CBO to use a plan, despite what hints and SQL profiles there are for a plan.

Use your baseline is loaded then get the sql handle from the dba_sql_plan_baselines view.

Try to evolve it using:

SET LONG 10000
SELECT DBMS_SPM.evolve_sql_plan_baseline(sql_handle => 'SQL_handle_xxxxxx') FROM dual;

var report clob;
exec :report := dbms_spm.evolve_sql_plan_baseline();
print :report

Evolution of the plan will only work as more plans become available.

Sometimes you need to fix it to force the baseline, for example:

SET SERVEROUTPUT ON
DECLARE
  l_plans_altered  PLS_INTEGER;
BEGIN
  l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
    sql_handle      => 'SQL_handle_xxxxxx',
    plan_name       => 'SQL_PLAN_xxxxxxx',
    attribute_name  => 'fixed',
    attribute_value => 'YES');
  DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
END;
/

Usually the plan will not be used immediately and there are various methods to try and force it...

One is to kill all sessions running that statement, if viable.

You can also invalidate the cursor using the table:

begin
  dbms_stats.gather_table_stats(ownname=> '<schema>',
  tabname=> '<table>', no_invalidate => FALSE);
end;

Analyzing using the old method will also invalidate the cursor!

SQL> analyze table <table> estimate statistics sample 1 percent;

To check:

SQL> select child_number, executions, parse_calls, loads, invalidations 
     from v$sql where sql_id = '<SQLID>';

Sequence of events:

  1. Lock the user
  2. Invalidate the cursor
  3. Kill all sessions logged in as that user
  4. Unlock the user
  5. Check again


来源:https://stackoverflow.com/questions/41858149/how-to-force-accept-a-sql-plan-baseline

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!