且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[20131111]参数optimizer_features_enable.txt

更新时间:2022-09-08 12:17:00

[20131111]参数optimizer_features_enable.txt

optimizer_features_enable可以使系统升级后保持原来的执行计划。我自己很少做这种升级操作,昨天在给别人做优化时遇到一个问题,
自己做一个记录,用户改动了参数optimizer_features_enable,不知道什么原因要改这个参数,导致一些执行计划很慢!

举一个例子:

1.建立测试环境:
SCOTT@test> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

SCOTT@test> show parameter  optimizer_features_enable ;
NAME                                 TYPE                                     VALUE
------------------------------------ ---------------------------------------- ---------
optimizer_features_enable            string                                   11.2.0.3

drop table t1 purge;
drop table t2 purge;
create table t1 as select rownum id ,lpad('t1',6,'x') v1 from dual connect by level
create table t2 as select rownum+1 id ,lpad('t2',6,'x') v1 from dual connect by level

exec dbms_stats.gather_table_stats(user,'T1',cascade=>TRUE);
exec dbms_stats.gather_table_stats(user,'T2',cascade=>TRUE);

2.测试:
SCOTT@test> select t1.* from t1 where not exists ( select 1 from t2  where t2.id=t1.id);
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1

SCOTT@test> select t1.* from t1 where t1.id not in ( select id from t2 );
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1

--使用not in ,not exists都很快出结果。

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
SQL_ID  18h1xv8u3xwa5, child number 0
-------------------------------------
select t1.* from t1 where t1.id not in ( select id from t2 )
Plan hash value: 2739594415
-----------------------------------------------------------------------------------------
| Id  | Operation               | Name | E-Rows | Cost (%CPU)|  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |        |    19 (100)|       |       |          |
|*  1 |  HASH JOIN RIGHT ANTI NA|      |    100 |    19   (6)|  1517K|  1517K| 1946K (0)|
|   2 |   TABLE ACCESS FULL     | T2   |   9998 |     9   (0)|       |       |          |
|   3 |   TABLE ACCESS FULL     | T1   |  10000 |     9   (0)|       |       |          |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."ID"="ID")

SCOTT@test> alter session set optimizer_features_enable = '9.2.0.8';
Session altered.

SCOTT@test> SET TIMING ON
SCOTT@test> select t1.* from t1 where t1.id not in ( select id from t2 );
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1
Elapsed: 00:00:03.45
--需要4秒,实际的系统比这个还慢!

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------
SQL_ID  18h1xv8u3xwa5, child number 1
-------------------------------------
select t1.* from t1 where t1.id not in ( select id from t2 )
Plan hash value: 895956251
----------------------------------------------------
| Id  | Operation          | Name | E-Rows | Cost  |
----------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |    12 |
|*  1 |  FILTER            |      |        |       |
|   2 |   TABLE ACCESS FULL| T1   |    500 |     6 |
|*  3 |   TABLE ACCESS FULL| T2   |      1 |     6 |
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( IS NULL)
   3 - filter(LNNVL("ID":B1))

Note
-----
   - cpu costing is off (consider enabling it)
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
28 rows selected.   

--我开始以为not in与not exists的区别。但是执行计划的note中出现一个很奇怪的提示
- cpu costing is off (consider enabling it),好像没有见过。不过当时没特别的在意。

--看看not exists的情况,发现执行计划不同。注意我以前写的一篇blog
-- http://space.itpub.net/267265/viewspace-747842/
-- [20121028]not in与NULL问题.txt

SCOTT@test> select t1.* from t1 where not exists ( select 1 from t2  where t2.id=t1.id);
        ID V1
---------- ------
     10000 xxxxt1
         1 xxxxt1

Elapsed: 00:00:00.02
SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
SQL_ID  ajfxx4ykgyxm6, child number 1
-------------------------------------
select t1.* from t1 where not exists ( select 1 from t2  where
t2.id=t1.id)
Plan hash value: 2706079091
-------------------------------------------------------------------------------
| Id  | Operation          | Name | E-Rows | Cost  |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |    15 |       |       |          |
|*  1 |  HASH JOIN ANTI    |      |      2 |    15 |  1278K|  1278K| 1670K (0)|
|   2 |   TABLE ACCESS FULL| T1   |  10000 |     6 |       |       |          |
|   3 |   TABLE ACCESS FULL| T2   |   9998 |     6 |       |       |          |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T2"."ID"="T1"."ID")
Note
-----
   - cpu costing is off (consider enabling it)
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
28 rows selected.

--建立的索引看看。
create index i_t1_id on t1(id);
create index i_t2_id on t2(id);

SCOTT@test> select t1.* from t1 where t1.id not in ( select id from t2 );
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1

Elapsed: 00:00:03.59
SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------
SQL_ID  18h1xv8u3xwa5, child number 0
-------------------------------------
select t1.* from t1 where t1.id not in ( select id from t2 )
Plan hash value: 895956251
----------------------------------------------------
| Id  | Operation          | Name | E-Rows | Cost  |
----------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |    12 |
|*  1 |  FILTER            |      |        |       |
|   2 |   TABLE ACCESS FULL| T1   |    500 |     6 |
|*  3 |   TABLE ACCESS FULL| T2   |      1 |     6 |
----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( IS NULL)
   3 - filter(LNNVL("ID":B1))
Note
-----
   - cpu costing is off (consider enabling it)
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
28 rows selected.

--而使用not exists确实是快一些,主要是使用I_T2_ID索引。

SCOTT@test> select t1.* from t1 where not exists ( select 1 from t2  where t2.id=t1.id);
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1

Elapsed: 00:00:00.05
SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
SQL_ID  ajfxx4ykgyxm6, child number 1
-------------------------------------
select t1.* from t1 where not exists ( select 1 from t2  where
t2.id=t1.id)
Plan hash value: 43495135
-------------------------------------------------------
| Id  | Operation          | Name    | E-Rows | Cost  |
-------------------------------------------------------
|   0 | SELECT STATEMENT   |         |        |     7 |
|*  1 |  FILTER            |         |        |       |
|   2 |   TABLE ACCESS FULL| T1      |    500 |     6 |
|*  3 |   INDEX RANGE SCAN | I_T2_ID |      1 |     1 |
-------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter( IS NULL)
   3 - access("T2"."ID"=:B1)

Note
-----
   - cpu costing is off (consider enabling it)
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
29 rows selected.

--我再仔细观察发现就是执行 select sysdate from dual ;这样的语句,执行计划里面也有这些信息,是否用户使用什么隐含参数?
- cpu costing is off (consider enabling it)

3.检查参数文件:
发现用户修改了参数optimizer_features_enable = '9.2.0.8',修改回来后,执行一些正常。

SCOTT@test> alter session set optimizer_features_enable = '11.2.0.3';
Session altered.

SCOTT@test> select t1.* from t1 where t1.id not in ( select id from t2 );
        ID V1
---------- ------
         1 xxxxt1
     10000 xxxxt1

SCOTT@test> @dpc '' ''
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
SQL_ID  18h1xv8u3xwa5, child number 1
-------------------------------------
select t1.* from t1 where t1.id not in ( select id from t2 )
Plan hash value: 2739594415
-----------------------------------------------------------------------------------------
| Id  | Operation               | Name | E-Rows | Cost (%CPU)|  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |        |    19 (100)|       |       |          |
|*  1 |  HASH JOIN RIGHT ANTI NA|      |    100 |    19   (6)|  1517K|  1517K| 1843K (0)|
|   2 |   TABLE ACCESS FULL     | T2   |   9998 |     9   (0)|       |       |          |
|   3 |   TABLE ACCESS FULL     | T1   |  10000 |     9   (0)|       |       |          |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."ID"="ID")
Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
26 rows selected.

--问修改原因,对方也讲不出来,看来取消设置,应该没有问题。

总结:
以后要注意看执行计划的细节,这样才能避免走弯路。