• Oracle 11g 执行计划管理2


    1.创建测试数据

    SQL> conn NC50/NC50
    Connected.
    SQL> create table tab1(id number,object_name varchar2(100));    
    SQL> insert into tab1 select rownum,object_name from dba_objects;
    SQL> commit;
    SQL> set line 180
    SQL> select * from tab1 where id=200;
    SQL> select * from tab1 where id=200;

      尽管执行两次,但是这时去查询dba_sql_plan_baselines,试图找到SQL文本为select * from tab1 where id=200;的记录时,会发现没有记录,因为optimizer_capture_sql_plan_baselines缺省为false。我们将该参数设置为true以后继续测试

    SQL> show parameter optimizer_capture_sql_plan_baselines
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    optimizer_capture_sql_plan_baselines boolean     FALSE
    SQL> select * from dba_sql_plan_baselines where SQL_TEXT like '%tab1%';
    no rows selected
    SQL> 

    2.开启自动捕获

    SQL> alter session set optimizer_capture_sql_plan_baselines=true;
    SQL> set line 180
    SQL> set autotrace off
    SQL> select * from tab1 where id=200;
    
            ID OBJECT_NAME
    ---------- ----------------------------------------------------------------------------------------------------
           200 SYS_LOB0000000207C00007$$
    
    --查看对应的执行计划
    SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge
      2  from dba_sql_plan_baselines 
      3  where sql_text like 'select * from tab1 where id=200';
    
     SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC FIX AUT
    ---------- ------------------------------ ------------------------------ -------------- --- --- --- ---
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbuec7b7588 AUTO-CAPTURE   YES YES NO  YES
    
    SQL>
    可以看到,SQL语句在plan history里产生了一个执行计划。其中:
    sql_handle表示SQL语句的句柄;
    plan_name则表示该SQL的执行计划的名字;
    origin表示该执行计划是如何进入plan history的,该列值为AUTO-CAPTURE则说明是由优化器自动加入的,如果为MANUAL则说明是由DBA手工加入的;
    Enabled (控制活动):
      + YES (活动的,但不一定会被使用)
      + NO (可以理解为被标记删除)
    Accepted(控制使用):
      + YES (只有 “Enabled” 并且“Accepted” 的计划才会被选择使用)
      + NO (如果是“Enabled” 那么只有被evolve成“Accepted”才有可能被执行)
    Fixed(控制优先级):
      + YES (如果是“Enabled”并且“Accepted”,会优先选择这个计划,这个计划会被视为不需要改变的)
      + NO (普通的计划,无需优先)
    autopurge表示该执行计划是否为定期自动删除,YES表示是,NO表示否。

      继续测试,在id上添加一个索引,从而让原来的SQL不走全表扫描,而改走索引扫描

    SQL> create index idx_tab1 on tab1(id);
    SQL> exec dbms_stats.gather_table_stats('NC50','tab1',cascade=>true);
    SQL> select * from tab1 where id=200;
    
            ID OBJECT_NAME
    ---------- ----------------------------------------------------------------------------------------------------
           200 SYS_LOB0000000207C00007$$
    
    SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge
      2  from dba_sql_plan_baselines 
      3  where sql_text like 'select * from tab1 where id=200';
    
     SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC FIX AUT
    ---------- ------------------------------ ------------------------------ -------------- --- --- --- ---
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbu61724234 AUTO-CAPTURE   YES NO  NO  YES
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbuec7b7588 AUTO-CAPTURE   YES YES NO  YES

      这时我们可以看到,dba_sql_plan_baselines视图里多了一个执行计划,也就是我们后面那个使用了索引扫描的执行计划。而该执行计划的accepted为NO,说明该计划并没有进入plan baseline里,但是进入了plan history里。因为新生成的为不是ACCEPTED,所以不被启用。验证如下:

    SQL> set autotrace traceonly explain
    SQL> select * from tab1 where id=200;
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2211052296
    
    --------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |      |     1 |    28 |   112   (1)| 00:00:02 |
    |*  1 |  TABLE ACCESS FULL| TAB1 |     1 |    28 |   112   (1)| 00:00:02 |
    --------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("ID"=200)
    
    Note
    -----
       - SQL plan baseline "SQL_PLAN_78rd4sbku9fbuec7b7588" used for this statement  
    
    SQL>

      启用的执行计划不是高效的(SQL_PLAN_78rd4sbku9fbu61724234),而是全表扫描的(SQL_PLAN_78rd4sbku9fbuec7b7588)。启用高效的执行计划之前,需要
    手动将执行计划演化成ACCEPTED

    3.现将新生成的执行计划演化成ACCEPTED

    SQL> set autotrace off
    SQL> SELECT DBMS_SPM.evolve_sql_plan_baseline(sql_handle => 'SYS_SQL_745da4c2e5a4b97a') FROM   dual;
    SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge
      2  from dba_sql_plan_baselines 
      3  where sql_text like 'select * from tab1 where id=200';
    
     SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC FIX AUT
    ---------- ------------------------------ ------------------------------ -------------- --- --- --- ---
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbu61724234 AUTO-CAPTURE   YES YES NO  YES
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbuec7b7588 AUTO-CAPTURE   YES YES NO  YES
    
    SQL>
     
    --查看 当前所走的执行计划
    SQL> set autotrace traceonly explain
    SQL> select * from tab1 where id=200;
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2722636538
    
    ----------------------------------------------------------------------------------------
    | Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |          |     1 |    28 |     2   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| TAB1     |     1 |    28 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | IDX_TAB1 |     1 |       |     1   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("ID"=200)
    
    Note
    -----
       - SQL plan baseline "SQL_PLAN_78rd4sbku9fbu61724234" used for this statement
    
    SQL>

      结论:存在多个( “Enabled”“Accepted”)的计划时,选择cost最小的

    4.删除Plans 和 Baselines

    DECLARE
     l_plans_dropped  PLS_INTEGER;
    BEGIN
     l_plans_dropped := DBMS_SPM.drop_sql_plan_baseline (
       sql_handle => 'SYS_SQL_745da4c2e5a4b97a',
       plan_name  => 'SQL_PLAN_78rd4sbku9fbu61724234');
       
     DBMS_OUTPUT.put_line(l_plans_dropped);
    END;
    
    SQL> set autotrace off
    SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge
      2  from dba_sql_plan_baselines 
      3  where sql_text like 'select * from tab1 where id=200';
    
     SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC FIX AUT
    ---------- ------------------------------ ------------------------------ -------------- --- --- --- ---
    8.3850E+18 SYS_SQL_745da4c2e5a4b97a       SQL_PLAN_78rd4sbku9fbuec7b7588 AUTO-CAPTURE   YES YES NO  YES
    
    SQL> 
  • 相关阅读:
    简单Android HttpURLConnectionGet方式
    异步加载图片
    平时收集的一些有关UED的团队和个人博客
    一道关于https进行登录验证的前端面试题
    IE下li的诡异边界问题
    关于Javascript框架的神回帖,值得围观
    jQuery中使用getJSON传递html文本
    CodeIgniter 去掉 URL 中的 index.php
    彻底解决跨浏览器下PHP下载文件名中的中文乱码问题
    php多维数组排序的方法
  • 原文地址:https://www.cnblogs.com/polestar/p/4458062.html
Copyright © 2020-2023  润新知