ITPub博客

首页 > 数据库 > Oracle > 控制执行计划之-SPM BASELINE(四)

控制执行计划之-SPM BASELINE(四)

原创 Oracle 作者:wei-xh 时间:2014-07-29 16:56:51 0 删除 编辑

Baseline Internal

 我们接着上面一节继续来思考,一个SQL在dba_sql_plan_baselines中存在2个accepted为YES状态的baseline。优化器如何决定使用哪一个?看到网上有些文章提到是依据dba_sql_plan_baselines. OPTIMIZER_COST来决定,哪个baseline对应的执行计划的cost小,就使用哪个。但是很容易验证说法是错误的。我们可以修改dba_sql_plan_baselines视图的基表sqlobj$auxdata中的OPTIMIZER_COST字段,来调整2个baseline的OPTIMIZER_COST的大小,但是实验结果最终证明是无效的,并不是通过dba_sql_plan_baselines. OPTIMIZER_COST的大小来决定使用哪个baseline。实验结果这里不再贴出。那到底是如何决定呢?这个要根据系统的配置来定,我们接着上面的例子,但是先关闭ACS,但是绑定变量窥探的功能保持打开。

test@DLSP>show parameter _optimizer_extended_cursor_sharing_rel

 

NAME                                   TYPE                   VALUE

-------------------------------------- ---------------------- --------

_optimizer_extended_cursor_sharing_rel string                 NONE

 

test@DLSP>show parameter bind

 

NAME                                 TYPE                   VALUE

------------------------------------ ---------------------- -----------

_optim_peek_user_binds               boolean                TRUE

 

test@DLSP>alter system flush shared_pool;

 

System altered.

提示:针对这个SQL当前在dba_sql_plan_baselines视图中存在2个baseline。

test@DLSP>ALTER SYSTEM FLUSH SHARED_POOL;

 

System altered.

 

test@DLSP>var a varchar2(100)

test@DLSP>exec :a :='Inactive'

 

PL/SQL procedure successfully completed.

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

        100

 

test@DLSP>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

------------------------------------------------------------------------------------------------------------------------------------------------------

SQL_ID  aa8mzbnrzu42f, child number 0

-------------------------------------

select count(name) from test where status= :a

 

Plan hash value: 4130896540

 

--------------------------------------------------------------------------------------

| Id  | Operation                    | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |       |       |       |     2 (100)|          |

|   1 |  SORT AGGREGATE              |       |     1 |    25 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| TEST  |   100 |  2500 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | T_IND |   100 |       |     1   (0)| 00:00:01 |

--------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   3 - access("STATUS"=:A)

 

Note

-----

   - SQL plan baseline SQL_PLAN_636ys750p7z8519ccc485 used for this statement

 

当对status的绑定值传入Inactive时,选用了我们进化后的baseline。由于列上存在直方图信息,我们看到了执行计划的输出基数部分非常的准确。这也要归功于绑定变量窥探的作用。上面读者可以再继续试试多次执行这个SQL,执行计划都会一直使用索引扫描。我们继续试验,看看重新刷新共享池,对status的绑定之传入Active会怎么样:

test@DLSP>alter system flush shared_pool;

 

System altered.

 

test@DLSP>exec :a :='Active';

 

PL/SQL procedure successfully completed.

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

      49900

 

test@DLSP>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  aa8mzbnrzu42f, child number 0

-------------------------------------

select count(name) from test where status= :a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 49900 |  1218K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

 

Note

-----

   - SQL plan baseline SQL_PLAN_636ys750p7z856b581ab9 used for this statement

已经选用了我们最初创建的baseline,执行计划已经走了全表扫描了。虽然baseline的作用是为了稳固执行计划,但是就像我们看到的,由于同一个SQL存在2个可接受的baseline,因此执行计划发生了不稳固的现象,绑定变量窥探的害处在这里又重新体现出来了。其实绑定变量和ACS都会在baseline起作用前就会发生,但是绑定变量窥探和ACS发挥作用后产生的执行计划必须从baseline中选用。因此就会发生前面产生的场景,绑定变量窥探导致已经使用baseline的SQL的执行计划不稳定。这种情况可以通过ACS来解决:

--------开启ACS

test@DLSP>alter system set "_optimizer_extended_cursor_sharing_rel"=simple ;

 

System altered.

 

test@DLSP>alter system flush shared_pool;

 

System altered.

 

test@DLSP>exec :a :='Active';

 

PL/SQL procedure successfully completed.

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

      49900

 

test@DLSP>select * from table(dbms_xplan.display_cursor);

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  aa8mzbnrzu42f, child number 0

-------------------------------------

select count(name) from test where status= :a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 49900 |  1218K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

 

Note

-----

   - SQL plan baseline SQL_PLAN_636ys750p7z856b581ab9 used for this statement

 

 

23 rows selected.

 

test@DLSP> -- 检查ACS状态

test@DLSP>SELECT child_number, executions, buffer_gets, is_bind_sensitive,IS_SHAREABLE,

  2           is_bind_aware

  3      FROM v$sql

  4     WHERE sql_id='aa8mzbnrzu42f';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS IS

------------ ---------- ----------- -- -- --

           0          1         452 Y  Y  N

 

-- 直方图

SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

test@DLSP>test@DLSP>  2        FROM v$sql_cs_histogram

  3       WHERE sql_id='aa8mzbnrzu42f'

  4    ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID                     CHILD_NUMBER  BUCKET_ID      COUNT

---------- -------------------------- ------------ ---------- ----------

 805113934 aa8mzbnrzu42f                         0          0          0

 805113934 aa8mzbnrzu42f                         0          2          0

 805113934 aa8mzbnrzu42f                         0          1          1

 

test@DLSP>exec :a :='Inactive';

 

PL/SQL procedure successfully completed.

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

        100

 

test@DLSP> -- 检查ACS状态

test@DLSP>SELECT child_number, executions, buffer_gets, is_bind_sensitive,IS_SHAREABLE,

  2           is_bind_aware

  3      FROM v$sql

  4     WHERE sql_id='aa8mzbnrzu42f';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS IS

------------ ---------- ----------- -- -- --

           0          2         662 Y  Y  N

 

 

test@DLSP>-- 直方图

test@DLSP>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2        FROM v$sql_cs_histogram

  3       WHERE sql_id='aa8mzbnrzu42f'

  4    ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID                     CHILD_NUMBER  BUCKET_ID      COUNT

---------- -------------------------- ------------ ---------- ----------

 805113934 aa8mzbnrzu42f                         0          0          1

 805113934 aa8mzbnrzu42f                         0          2          0

 805113934 aa8mzbnrzu42f                         0          1          1

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

        100

 

test@DLSP> -- 检查ACS状态

test@DLSP>SELECT child_number, executions, buffer_gets, is_bind_sensitive,IS_SHAREABLE,

  2           is_bind_aware

  3      FROM v$sql

  4     WHERE sql_id='aa8mzbnrzu42f';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS IS

------------ ---------- ----------- -- -- --

           0          2         662 Y  N  N

           1          1         102 Y  Y  Y

 

test@DLSP>-- 直方图

test@DLSP>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2        FROM v$sql_cs_histogram

  3       WHERE sql_id='aa8mzbnrzu42f'

  4    ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID                     CHILD_NUMBER  BUCKET_ID      COUNT

---------- -------------------------- ------------ ---------- ----------

 805113934 aa8mzbnrzu42f                         0          1          1

 805113934 aa8mzbnrzu42f                         0          0          1

 805113934 aa8mzbnrzu42f                         0          2          0

 805113934 aa8mzbnrzu42f                         1          1          0

 805113934 aa8mzbnrzu42f                         1          0          1

 805113934 aa8mzbnrzu42f                         1          2          0

 

6 rows selected.

 

--------查看child_number为1的执行计划

test@DLSP>select * from table(dbms_xplan.display_cursor('aa8mzbnrzu42f',1));

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  aa8mzbnrzu42f, child number 1

-------------------------------------

select count(name) from test where status= :a

 

Plan hash value: 4130896540

 

--------------------------------------------------------------------------------------

| Id  | Operation                    | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT             |       |       |       |     2 (100)|          |

|   1 |  SORT AGGREGATE              |       |     1 |    25 |            |          |

|   2 |   TABLE ACCESS BY INDEX ROWID| TEST  |   100 |  2500 |     2   (0)| 00:00:01 |

|*  3 |    INDEX RANGE SCAN          | T_IND |   100 |       |     1   (0)| 00:00:01 |

--------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   3 - access("STATUS"=:A)

 

Note

-----

   - SQL plan baseline SQL_PLAN_636ys750p7z8519ccc485 used for this statement

 

test@DLSP>exec :a :='Active';

 

PL/SQL procedure successfully completed.

 

test@DLSP>select count(name) from test where status= :a;

 

COUNT(NAME)

-----------

      49900

 

test@DLSP> -- 检查ACS状态

test@DLSP>SELECT child_number, executions, buffer_gets, is_bind_sensitive,IS_SHAREABLE,

  2           is_bind_aware

  3      FROM v$sql

  4     WHERE sql_id='aa8mzbnrzu42f';

 

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS IS IS

------------ ---------- ----------- -- -- --

           0          2         662 Y  N  N

           1          1         102 Y  Y  Y

           2          1         210 Y  Y  Y

 

test@DLSP>-- 直方图

test@DLSP>SELECT   hash_value, sql_id, child_number, bucket_id, COUNT

  2        FROM v$sql_cs_histogram

  3       WHERE sql_id='aa8mzbnrzu42f'

  4    ORDER BY sql_id, child_number;

 

HASH_VALUE SQL_ID                     CHILD_NUMBER  BUCKET_ID      COUNT

---------- -------------------------- ------------ ---------- ----------

 805113934 aa8mzbnrzu42f                         0          1          1

 805113934 aa8mzbnrzu42f                         0          0          1

 805113934 aa8mzbnrzu42f                         0          2          0

 805113934 aa8mzbnrzu42f                         1          0          1

 805113934 aa8mzbnrzu42f                         1          1          0

 805113934 aa8mzbnrzu42f                         1          2          0

 805113934 aa8mzbnrzu42f                         2          1          1

 805113934 aa8mzbnrzu42f                         2          0          0

 805113934 aa8mzbnrzu42f                         2          2          0

 

9 rows selected.

 

test@DLSP>select * from table(dbms_xplan.display_cursor('aa8mzbnrzu42f',2));

 

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------

SQL_ID  aa8mzbnrzu42f, child number 2

-------------------------------------

select count(name) from test where status= :a

 

Plan hash value: 1950795681

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |       |       |    51 (100)|          |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| TEST | 49900 |  1218K|    51   (2)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("STATUS"=:A)

 

Note

-----

   - SQL plan baseline SQL_PLAN_636ys750p7z856b581ab9 used for this statement

 

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22034023/viewspace-1241481/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE组成员,DBGeeK用户组发起人。曾在DTCC、ORACLE技术嘉年华、Gdevops等公开场合做过数据库技术专题分享,2017年应Oracle邀请在世界最大的数据库会议OOW上做技术分享。组织翻译了《拨云见日,解密Oracle ASM内核》一书。

注册时间:2009-07-04

  • 博文量
    422
  • 访问量
    2425323