如何强制接受SQL计划基准?

时间:2017-01-25 17:42:48

标签: oracle oracle11g sql-execution-plan oracle-enterprise-manager

在Oracle中(在Oracle企业管理器中查看)我有一个特定的SQL Plan Baseline,设置为Enabled = YES。

但是,我无法获得ACCEPTED = YES。根据文档,您需要ENABLED和ACCEPTED两者。

我试图"进化"基线,但OEM(通过报告)抱怨它的情况要差1.06倍。但事实并非如此。

此外,我想知道如何确保它不会随着时间的推移自动清除并且它已被修复。谢谢!

1 个答案:

答案 0 :(得分:4)

要启用基线使用, optimizer_use_sql_plan_baselines 必须为true。

SELECT * FROM dba_sql_plan_baselines

考虑具有最低成本或最佳经过时间的计划的基线。优化程序将选择成本最低的计划,但会优先考虑固定计划。这是保证CBO使用计划的最佳方式,尽管有一些计划的提示和SQL配置文件。

使用你的基线加载,然后从dba_sql_plan_baselines视图中获取sql句柄。

尝试使用以下方式进化

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

计划的演变只会在更多计划可用时才有效。

有时你需要修复来强制基线,例如:

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;
/

通常不会立即使用该计划,并且有各种方法可以尝试强制它......

一种方法是杀死运行该语句的所有会话,如果可行的话。

您还可以使用表格使游标无效:

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

使用旧方法进行分析也会使光标无效!

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

检查:

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

事件顺序:

  
      
  1. 锁定用户
  2.   
  3. 使光标无效
  4.   
  5. 终止以该用户身份登录的所有会话
  6.   
  7. 解锁用户
  8.   
  9. 再次检查
  10.