父子游标不可共享的情况分析

解析操作的结果就是一个父游标和一个子游标存储在库缓存中的共享SQL区中。
以下分三个部分讨论一个游标在哪里不能进行共享。
1.父游标在哪里不能进行共享。
2.父游标可以共享情况下子游标什么时候不能共享。

3.执行环境不仅影响执行计划还有可能影响SQL执行结果。


--实验1.父游标在哪里不能进行共享。
SCOTT@PROD1> DROP TABLE t;

Table dropped.

SCOTT@PROD1> 
SCOTT@PROD1> CREATE TABLE t
  2  AS
  3  SELECT rownum AS n, rpad('*',100,'*') AS pad
  4  FROM dual
  5  CONNECT BY level <= 1000;

Table created.

SCOTT@PROD1> 
SCOTT@PROD1> execute dbms_stats.gather_table_stats(ownname=>user, tabname=>'t')

PL/SQL procedure successfully completed.

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SYSTEM FLUSH SHARED_POOL;

System altered.

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET cursor_sharing = 'EXACT';

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT * FROM t WHERE n = 1234;

no rows selected

SCOTT@PROD1> 
SCOTT@PROD1> select * from t where n = 1234;

no rows selected

SCOTT@PROD1> 
SCOTT@PROD1> SELECT	*	FROM  t  WHERE	n=1234;

no rows selected

SCOTT@PROD1> 
SCOTT@PROD1> SELECT * FROM t WHERE n = 1234;

no rows selected

SCOTT@PROD1> 
SCOTT@PROD1> SELECT * FROM t WHERE n = 01234;

no rows selected

SCOTT@PROD1> COLUMN sql_text FORMAT A36
SCOTT@PROD1> SELECT sql_id, sql_text, executions
  2  FROM v$sqlarea
  3  WHERE sql_text LIKE '%1234';

SQL_ID	      SQL_TEXT				   EXECUTIONS
------------- ------------------------------------ ----------
6vdany43w59xn SELECT * FROM t WHERE n = 01234		    1
2254m1487jg50 select * from t where n = 1234		    1
g9y3jtp6ru4cb SELECT * FROM t WHERE n = 1234		    2
7n8p5s2udfdsn SELECT  *  FROM  t  WHERE  n=1234 	    1

--字母大小写与空格数的不一致都会导致父游标不能被共享。


--实验2.父游标可以共享情况下子游标什么时候不能共享。

SCOTT@PROD1> COLUMN sql_text FORMAT A22
SCOTT@PROD1> COLUMN optimizer_mode FORMAT A14
SCOTT@PROD1> COLUMN optimizer_mode_mismatch FORMAT A1
SCOTT@PROD1> COLUMN optimizer_mismatch FORMAT A1
SCOTT@PROD1> COLUMN xml_reason FORMAT A80
SCOTT@PROD1> COLUMN reason FORMAT A22
SCOTT@PROD1> COLUMN optimizer_mode_cursor FORMAT A21
SCOTT@PROD1> COLUMN optimizer_mode_current FORMAT A22
SCOTT@PROD1> COLUMN language_mismatch FORMAT A17
SCOTT@PROD1> 
SCOTT@PROD1> COLUMN sql_id NEW_VALUE sql_id
SCOTT@PROD1> 
SCOTT@PROD1> DROP TABLE t;

Table dropped.

SCOTT@PROD1> 
SCOTT@PROD1> CREATE TABLE t
  2  AS
  3  SELECT rownum AS n, rpad('*',100,'*') AS pad
  4  FROM dual
  5  CONNECT BY level <= 1000;

Table created.

SCOTT@PROD1> 
SCOTT@PROD1> execute dbms_stats.gather_table_stats(ownname=>user, tabname=>'t')

PL/SQL procedure successfully completed.

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SYSTEM FLUSH SHARED_POOL;

System altered.

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET cursor_sharing = 'EXACT';

Session altered.

SCOTT@PROD1> ALTER SESSION SET optimizer_mode = all_rows;

Session altered.

SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> ALTER SESSION SET optimizer_mode = first_rows_1;

Session altered.

SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> start /tmp/1.sql
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = first_rows_10;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = first_rows_100;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = first_rows_1000;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = first_rows;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = rule;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET optimizer_mode = choose;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT count(*) FROM t;

  COUNT(*)
----------
      1000

SCOTT@PROD1> 
SCOTT@PROD1> SELECT sql_id, child_number, optimizer_mode, plan_hash_value, executions
  2  FROM v$sql
  3  WHERE sql_text = 'SELECT count(*) FROM t';

SQL_ID	      CHILD_NUMBER OPTIMIZER_MODE PLAN_HASH_VALUE EXECUTIONS
------------- ------------ -------------- --------------- ----------
5tjqf7sx5dzmj		 0 ALL_ROWS	       2966233522	   1
5tjqf7sx5dzmj		 1 FIRST_ROWS	       2966233522	   5
5tjqf7sx5dzmj		 2 RULE 	       2966233522	   1
5tjqf7sx5dzmj		 3 CHOOSE	       2966233522	   1

--结果可以看出创建了一个父游标‘5tjqf7sx5dzmj’和四个子游标,而且拥有相同的执行计划。
--不过此处OPTIMIZER_MODE明显存在问题,first_rows_*都被识别为FIRST_ROWS,所以即使执行环境不一样,SQL也有可能错误共享子游标。

--通过查看v$sql_shared_cursor视图可以发现哪些不匹配导致出现了多个子游标。
--不匹配列值被设置为Y,匹配为N。
SCOTT@PROD1> 
SCOTT@PROD1> SELECT *
  2  FROM v$sql_shared_cursor
  3  WHERE sql_id = '&sql_id'
  4  AND child_number > 0;
old   3: WHERE sql_id = '&sql_id'
new   3: WHERE sql_id = '5tjqf7sx5dzmj'

SQL_ID	      ADDRESS  CHILD_AD CHILD_NUMBER U S O O S L F E B P I S T A B D LANGUAGE_MISMATCH T B I
------------- -------- -------- ------------ - - - - - - - - - - - - - - - - ----------------- - - -
I R L I O E M U T N F A P T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B U
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
REASON
----------------------
5tjqf7sx5dzmj 44AF3004 448E3358 	   1 N N N N N N N N N N N N N N N N N	         N N N
N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N N
<ChildNode><ChildNumbe
r>1</ChildNumber><ID>3
</ID><reason>Optimizer
 mismatch(10)</reason>
<size>3x4</size><optim
izer_mode_hinted_curso
r>0</optimizer_mode_hi
nted_cursor><optimizer
_mode_cursor>2</optimi
zer_mode_cursor><optim
izer_mode_current>3</o
ptimizer_mode_current>
</ChildNode>

5tjqf7sx5dzmj 44AF3004 4659611C 	   2 N N N N N N N N N N N N N N N N N	         N N N
N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N N
<ChildNode><ChildNumbe
r>2</ChildNumber><ID>3
</ID><reason>Optimizer
 mismatch(10)</reason>
<size>3x4</size><optim
izer_mode_hinted_curso
r>0</optimizer_mode_hi
nted_cursor><optimizer
_mode_cursor>3</optimi
zer_mode_cursor><optim
izer_mode_current>4</o
ptimizer_mode_current>
</ChildNode>

5tjqf7sx5dzmj 44AF3004 44AF3544 	   3 N N N N N N N N N N N N N N N N N	         N N N
N N N N N N N N N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N N

--在11.0.2中,v$sql_shared_cursor中提供reason列来提供不匹配的文字描述。
SCOTT@PROD1> SET LONG 1000
SCOTT@PROD1> 
SCOTT@PROD1> SELECT xmltype('<Root>'||reason||'</Root>').
  2  	      extract('/Root/ChildNode[1]').
  3  	      getstringval() AS xml_reason
  4  FROM v$sql_shared_cursor
  5  WHERE sql_id = '&sql_id';
old   5: WHERE sql_id = '&sql_id'
new   5: WHERE sql_id = '5tjqf7sx5dzmj'

XML_REASON
--------------------------------------------------------------------------------
<ChildNode><ChildNumber>0</ChildNumber><ID>3</ID><reason>Optimizer mismatch(10)<
/reason><size>3x4</size><optimizer_mode_hinted_cursor>0</optimizer_mode_hinted_c
ursor><optimizer_mode_cursor>1</optimizer_mode_cursor><optimizer_mode_current>2<
/optimizer_mode_current></ChildNode>

<ChildNode><ChildNumber>1</ChildNumber><ID>3</ID><reason>Optimizer mismatch(10)<
/reason><size>3x4</size><optimizer_mode_hinted_cursor>0</optimizer_mode_hinted_c
ursor><optimizer_mode_cursor>2</optimizer_mode_cursor><optimizer_mode_current>3<
/optimizer_mode_current></ChildNode>

<ChildNode><ChildNumber>2</ChildNumber><ID>3</ID><reason>Optimizer mismatch(10)<
/reason><size>3x4</size><optimizer_mode_hinted_cursor>0</optimizer_mode_hinted_c
ursor><optimizer_mode_cursor>3</optimizer_mode_cursor><optimizer_mode_current>4<
/optimizer_mode_current></ChildNode>



SCOTT@PROD1> 
SCOTT@PROD1> SELECT x.child_number, x.reason,
  2  	    decode(x.optimizer_mode_cursor, 1, 'ALL_ROWS',
  3  					    2, 'FIRST_ROWS',
  4  					    3, 'RULE',
  5  					    4, 'CHOOSE', x.optimizer_mode_cursor) AS optimizer_mode_cursor,
  6  	    decode(x.optimizer_mode_current, 1, 'ALL_ROWS',
  7  					     2, 'FIRST_ROWS',
  8  					     3, 'RULE',
  9  					     4, 'CHOOSE', x.optimizer_mode_current) AS optimizer_mode_current
 10  FROM v$sql_shared_cursor s,
 11  	  XMLTable('/Root'
 12  		   PASSING XMLType('<Root>'||reason||'</Root>')
 13  		   COLUMNS child_number NUMBER			PATH '/Root/ChildNode[1]/ChildNumber',
 14  			   id NUMBER				PATH '/Root/ChildNode[1]/ID',
 15  			   reason VARCHAR2(100) 		PATH '/Root/ChildNode[1]/reason',
 16  			   optimizer_mode_hinted_cursor NUMBER	PATH '/Root/ChildNode[1]/optimizer_mode_hinted_cursor',
 17  			   optimizer_mode_cursor NUMBER 	PATH '/Root/ChildNode[1]/optimizer_mode_cursor',
 18  			   optimizer_mode_current NUMBER	PATH '/Root/ChildNode[1]/optimizer_mode_current'
 19  			   ) x
 20  WHERE s.sql_id = '&sql_id';
old  20: WHERE s.sql_id = '&sql_id'
new  20: WHERE s.sql_id = '5tjqf7sx5dzmj'

CHILD_NUMBER REASON		    OPTIMIZER_MODE_CURSOR OPTIMIZER_MODE_CURRENT
------------ ---------------------- --------------------- ----------------------
	   0 Optimizer mismatch(10) ALL_ROWS		  FIRST_ROWS
	   1 Optimizer mismatch(10) FIRST_ROWS		  RULE
	   2 Optimizer mismatch(10) RULE		  CHOOSE

--实验3.执行环境不仅影响执行计划还有可能影响SQL执行结果。
SCOTT@PROD1> TRUNCATE TABLE t;

Table truncated.

SCOTT@PROD1> 
SCOTT@PROD1> INSERT INTO t VALUES (1, '1');

1 row created.

SCOTT@PROD1> INSERT INTO t VALUES (2, '=');

1 row created.

SCOTT@PROD1> INSERT INTO t VALUES (3, 'Z');

1 row created.

SCOTT@PROD1> INSERT INTO t VALUES (4, 'z');

1 row created.

SCOTT@PROD1> COMMIT;

Commit complete.

SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET nls_sort = binary;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT * FROM t ORDER BY pad;

	 N
----------
PAD
----------------------------------------------------------------------------------------------------
	 1
1

	 2
=

	 3
Z

	 4
z


SCOTT@PROD1> 
SCOTT@PROD1> ALTER SESSION SET nls_sort = xgerman;

Session altered.

SCOTT@PROD1> 
SCOTT@PROD1> SELECT * FROM t ORDER BY pad;

	 N
----------
PAD
----------------------------------------------------------------------------------------------------
	 2
=

	 4
z

	 3
Z

	 1
1


SCOTT@PROD1> 
SCOTT@PROD1> SELECT sql_id, child_number, plan_hash_value, executions
  2  FROM v$sql
  3  WHERE sql_text = 'SELECT * FROM t ORDER BY pad';

SQL_ID	      CHILD_NUMBER PLAN_HASH_VALUE EXECUTIONS
------------- ------------ --------------- ----------
1f7qg6nu40shd		 0	 961378228	    1
1f7qg6nu40shd		 1	 961378228	    1

SCOTT@PROD1> 
SCOTT@PROD1> SELECT child_number, language_mismatch
  2  FROM v$sql_shared_cursor
  3  WHERE sql_id = '&sql_id'
  4  AND child_number > 0;
old   3: WHERE sql_id = '&sql_id'
new   3: WHERE sql_id = '1f7qg6nu40shd'

CHILD_NUMBER LANGUAGE_MISMATCH
------------ -----------------
	   1 Y


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值