简单讨论在11G,10G中如何稳定SQL执行计划(二)

2014-11-24 10:16:21 · 作者: · 浏览: 7
ec dbms_stats.set_index_stats(ownname=>user,indname=>'HAHA_IDX',NUMROWS=>1,numdist=>1,no_invalidate=>false); PL/SQL procedure successfully completed. SQL> select * from haha where a='10000'; A B ------------------------------ ---------- 10000 10000 SQL> select sql_id,child_number,plan_hash_value,sql_text from v$sql where sql_text like '%haha where%'; SQL_ID CHILD_NUMBER PLAN_HASH_VALUE ------------- ------------ --------------- SQL_TEXT ------------------------------------------------------------------------------------------------------------------------------------------------------ auwza0aq10mk0 0 1624320650 select * from haha where a='10000' auwza0aq10mk0 1 3694936490 select * from haha where a='10000'

我们可以看到,这里已经产生了两个不同的执行计划,注意看PLAN_HASH_VALUE列。

我们来查询一下新产生的PLAN

SQL> select * from table(dbms_xplan.display_cursor('auwza0aq10mk0',1));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID	auwza0aq10mk0, child number 1
-------------------------------------
select * from haha where a='10000'

Plan hash value: 3694936490

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |	 |	 |    32 (100)| 	 |
|*  1 |  TABLE ACCESS FULL| HAHA |     1 |    11 |    32   (4)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"='10000')


18 rows selected.
这个新的PLAN,为全表扫描,是不正确的执行计划

现在我在当前环境下执行该sql,会一直采用这个错误的plan,在业务系统中是很致命的。

SQL> select * from haha where a='10000';

A					B
------------------------------ ----------
10000				    10000

SQL> select * from table(dbms_xplan.display_cursor());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID	auwza0aq10mk0, child number 1
-------------------------------------
select * from haha where a='10000'

Plan hash value: 3694936490

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |	 |	 |    32 (100)| 	 |
|*  1 |  TABLE ACCESS FULL| HAHA |     1 |    11 |    32   (4)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"='10000')


18 rows selected.

那么我想将正确的执行计划稳定上,该如何做?

通过使用11G的新包,DBMS_SPM就可以实现

SQL BASELINE有两个状态,一个是ENABLED,一个是ACCEPTED,两个都为true,oracle才会使用,如果有同一个SQL的多个SQL_BASELINE存在,且状态都为true,那么会根据成本大小进行判断。(注:当自动捕获开启时,一个SQL,每产生一个不同的执行计划,都会产生一个baseline,enabled都为true,但只有第一个获取的baseline,accepted才为true,其他都为false)

SQL>variable cnt number