cursor_sharing 三个参数的测试(exact-similar-force)

    Cursor_sharing参数有3个值可以设置:

     1)、EXACT:通常来说,exact值是Oracle推荐的,也是默认的,它要求SQL语句在完全相同时才会重用,否则会被重新执行硬解析操作。

     2)、SIMILAR:similar是在Oracle认为某条SQL语句的谓词条件可能会影响到它的执行计划时,才会被重新分析,否则将重用SQL。

     3)、FORCE:force是在任何情况下,无条件重用SQL。

先来测试一下这三种情况的区别:

实验环境:

oracle 11.2.0.3

建立测试表T1:

SQL> create table t1 as  select object_id as id,object_name from dba_objects where rownum<=10000;

SQL> create table t1_exact as select * from t1;

SQL> create  table t1_similar as select * from t1;

SQL> create table t1_force  as select * from t1;

建立一张测试表,并在id列添加索引。

1.当cursor_sharing值为exact时,它要求SQL语句在完全相同时才会重用,否则会被重新执行硬解析操作。

SQL> alter session set cursor_sharing=exact;

Session altered.

SQL> alter session set sql_trace=true;

Session altered.

SQL> select * from t1_exact where id=1;

no rows selected

SQL>  select * from t1_exact where id=2;

        ID
----------
OBJECT_NAME
--------------------------------------------------------------------------------
         2
C_OBJ#


SQL> select * from t1_exact where id=1;

no rows selected

SQL> alter session set sql_trace=false;

Session altered.

通过tkprof查看一下这样的语句被硬解析了几次?

select *
from
 t1_exact where id=1


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00         39         80          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        6      0.00       0.00         39         80          0           0

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 2

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         0          0          0  TABLE ACCESS FULL T1_EXACT (cr=40 pr=20 pw=0 time=1312 us cost=13 size=22 card=1)

谓词where id=1这条语句被执行了2次(execute),硬解析1次(misses in library cache during parse)

SQL ID: 6a6djdhd16kt0 Plan Hash: 2784782265

select *
from
 t1_exact where id=2


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0         41          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0         41          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS FULL T1_EXACT (cr=41 pr=0 pw=0 time=31 us cost=13 size=22 card=1)

 谓词where id=2这条语句被执行了1次(execute),硬解析1次(misses in library cache during parse)

可以看出,exact要求SQL完全一样才被重用。

2.对于SIMILAR的情况,如果CBO发现被绑定变量的谓词还有其他的执行计划可以选择时,如果谓词条件的值有变化,就将会产生一个新的子游标,而不是重用之前的SQL;如果谓词没有其他的执行计划可选择,则忽略谓词的值,重用之前的SQL。

为了测试similar的情况,需要对表增加一行数据,并且增加一个索引以便于说明:

SQL> insert into t1_similar values(3,'TEST');

1 row created.


SQL> create index i_t1_similar  on  t1_similar(id);

Index created.

SQL> exec dbms_stats.gather_table_stats(user,'t1_similar',cascade=>true);

PL/SQL procedure successfully completed.


SQL> select * from t1_similar where id between 3 and 5;

  ID OBJECT_NAME
---- --------------------
   3 I_OBJ#
   3 TEST
   4 TAB$
   5 CLU$

SQL> alter system flush shared_pool; --刷新一下share pool,否则有可能会影响硬解析的准确性

System altered.

接着开始执行sql,后面抓取trace:

SQL> alter session set cursor_sharing=similar;

Session altered.

SQL> alter session set sql_trace=true;

Session altered.


SQL>  select * from t1_similar where id=4;

  ID OBJECT_NAME
---- --------------------
   4 TAB$

SQL> select * from t1_similar where id=5;

  ID OBJECT_NAME
---- --------------------
   5 CLU$


SQL> select * from t1_similar where id=3 and object_name='I_OBJ#';

  ID OBJECT_NAME
---- --------------------
   3 I_OBJ#

SQL> select * from t1_similar where id=3 and object_name='TEST';

  ID OBJECT_NAME
---- --------------------
   3 TEST

SQL> alter session set sql_trace=false;

Session altered.

通过trkprof来查看生成的报告:

[oracle@qht131 trace]$ tkprof orcl_ora_2339.trc out.txt sys=no


select *
from
 t1_similar where id=:"SYS_B_0"


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.01          0         41          0           0
Execute      1      0.00       0.01          0          0          0           0
Fetch        2      0.00       0.00          0          4          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.03          0         45          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS BY INDEX ROWID T1_SIMILAR (cr=4 pr=0 pw=0 time=33 us cost=2 size=22 card=1)
         1          1          1   INDEX RANGE SCAN I_T1_SIMILAR (cr=3 pr=0 pw=0 time=28 us cost=1 size=0 card=1)(object id 78507)

********************************************************************************


SQL ID: 3ys4crhf25cgx Plan Hash: 1128109430

select *
from
 t1_similar where id=:"SYS_B_0"


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.00       0.00          0          4          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          4          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS BY INDEX ROWID T1_SIMILAR (cr=4 pr=0 pw=0 time=34 us cost=2 size=22 card=1)
         1          1          1   INDEX RANGE SCAN I_T1_SIMILAR (cr=3 pr=0 pw=0 time=31 us cost=1 size=0 card=1)(object id 78507)

********************************************************************************

当查询谓词分别为id=4和id=5时,分别都进行了硬解析(messes in library chche during parse:1)

SQL ID: ghf6gwn79fas0 Plan Hash: 1128109430

select *
from
 t1_similar where id=:"SYS_B_0" and object_name=:"SYS_B_1"


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        4      0.00       0.00          0         10          0           2
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        8      0.00       0.00          0         10          0           2

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 2

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS BY INDEX ROWID T1_SIMILAR (cr=5 pr=0 pw=0 time=40 us cost=2 size=22 card=1)
         2          2          2   INDEX RANGE SCAN I_T1_SIMILAR (cr=3 pr=0 pw=0 time=24 us cost=1 size=0 card=1)(object id 78507)

紧接着,当谓词为 id=3 and object_name='I_OBJ#'和 id=3 and object_name='TEST'时,报告里只有一条sql记录,记录了硬解析1次,不过execute为2,说明执行了2次。这里为什么没有2次硬解析?是因为这object_name的值发生了改变,但是id的值没有发生变,而id上有索引的,object_name上没有索引,CBO认为这样的情况不会改变SQL的执行计划。

3.最后是force的情况:

SQL> alter session set cursor_sharing=force;

Session altered.

SQL> alter session set sql_trace=true;

Session altered.

SQL> select * from t1_force where id=2;

  ID OBJECT_NAME
---- --------------------
   2 C_OBJ#

SQL> select * from t1_force where id=3;

  ID OBJECT_NAME
---- --------------------
   3 I_OBJ#

SQL> select * from t1_force where id=4;

  ID OBJECT_NAME
---- --------------------
   4 TAB$

SQL> select * from t1_force where id=1;

no rows selected

SQL> select * from t1_force where id=4;

  ID OBJECT_NAME
---- --------------------
   4 TAB$

SQL> alter session set sql_trace=false;

Session altered.

通过tkprof查看转义的信息:

SQL ID: f4wtdmc9wwj5g Plan Hash: 3904548038

select *
from
 t1_force where id=:"SYS_B_0"


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        5      0.00       0.01          0          0          0           0
Execute      5      0.00       0.00          0          0          0           0
Fetch        9      0.00       0.04         39        204          0           4
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       19      0.00       0.05         39        204          0           4

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 85
Number of plan statistics captured: 3

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS FULL T1_FORCE (cr=41 pr=13 pw=0 time=242 us cost=13 size=22 card=1)

这里只有一个sql id,这条sql执行了5次(execute为5),force的情况下所有sql都无条件地重用sql。

总结:

   FORCE和SIMIALR最大的区别在于,FORCE会把所有的谓词用变量代替,并且不管变量的值如何,一律重用第一条SQL语句,而SIMILAR会根据谓词的不同,来重新选择SQL的执行计划。

   如果一个系统,它存在变量绑定的问题,并且这种问题已经影响到了系统的性能,这时候可以考虑将参数cursor_sharing的值设置为SIMILAR或FORCE来改善这种局面,不过在改成SIMILAR或FORCE都可能带来一些Bug以及很多未知的东西,所以需要慎用。

   最后需要说明一点,对于OLTP系统,如果绑定变量情况不好的话,也许可以考虑通过设置这个参数来缓解一下问题;对于是在OLAP系统上,这个参数应该设置成EXACT,并且不应该使用绑定变量,因为在OLAP系统中,SQL的解析对于SQL的执行来看,话费的代价几乎可以忽略,而正确的SQL执行计划才是OLAP数据库最需要关注的。

猜你喜欢

转载自blog.csdn.net/jolly10/article/details/81285635