绑定变量窥探和直方图

绑定变量窥视cbo的一个附属功能,关闭他不会影响是用cbo还是rbo,就算关闭了绑定变量窥视,cbo还是会利用别的统计信息(num_distinct,density等)来评估cost和cardinality,只



是无法使用直方图信息而已:





SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

 FROM SYS.x$ksppi x, SYS.x$ksppcv y

 WHERE x.inst_id = USERENV ('Instance')

 AND y.inst_id = USERENV ('Instance')

 AND x.indx = y.indx

 AND x.ksppinm LIKE '%&par%';  2    3    4    5    6  

Enter value for par: peek_user

old   6:  AND x.ksppinm LIKE '%&par%'

new   6:  AND x.ksppinm LIKE '%peek_user%'



NAME VALUE DESCRIB

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



_optim_peek_user_binds TRUE enable peeking of user binds





当前开启绑定变量,开始测试:

SQL> alter system flush shared_pool;



System altered.



SQL> select sql_text,sql_id,a.executions from v$sql a 

where a.parsing_schema_name='SCOTT'

order by last_active_time desc;  2    3  



no rows selected







SQL> variable n number; 

SQL> exec :n := 7499;



PL/SQL procedure successfully completed.



SQL> select * from emp where empno = :n;



     EMPNO ENAME      JOB	       MGR HIREDATE	    SAL       COMM

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

    DEPTNO DNAME

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

      7499 ALLEN      SALESMAN	      7698 20-FEB-81	   1600        300

	30 UFO





SQL> select sql_text,sql_id,a.executions from v$sql a 

where a.parsing_schema_name='SCOTT'

order by last_active_time desc;   2    3  



SQL_TEXT		       SQL_ID	     EXECUTIONS

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

select * from emp where empno  3vv0t64yn0wrm	      1

= :n



BEGIN :n := 7499; END;	       2u1u06mytpsha	      1





SQL> exec :n := 7521;



PL/SQL procedure successfully completed.



SQL> select * from emp where empno = :n;



     EMPNO ENAME      JOB	       MGR HIREDATE	    SAL       COMM

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

    DEPTNO DNAME

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

      7521 WARD       SALESMAN	      7698 22-FEB-81	   1250        500

	30 UFO





查看执行次数:

SQL> select sql_text,sql_id,a.executions from v$sql a 

where a.parsing_schema_name='SCOTT'

order by last_active_time desc;  2    3  



SQL_TEXT		       SQL_ID	     EXECUTIONS

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

select * from emp where empno  3vv0t64yn0wrm	      2

= :n



BEGIN :n := 7521; END;	       9b4dm4tp4k58q	      1

BEGIN :n := 7499; END;	       2u1u06mytpsha	      1





此时说明代码完全共享



2.继续测试,关闭绑定变量窥探:

SQL> SQL>  alter system  set "_optim_peek_user_binds"=FALSE;



System altered.



Session altered.

SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

 FROM SYS.x$ksppi x, SYS.x$ksppcv y

 WHERE x.inst_id = USERENV ('Instance')

 AND y.inst_id = USERENV ('Instance')

 AND x.indx = y.indx

 AND x.ksppinm LIKE '%&par%';  2    3    4    5    6  

Enter value for par: peek_user

old   6:  AND x.ksppinm LIKE '%&par%'

new   6:  AND x.ksppinm LIKE '%peek_user%'



NAME

----------

VALUE

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



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

DESCRIB

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



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

_optim_pee

k_user_bin

ds

FALSE

enable peeking of user binds



此时绑定变量已经关闭:

SQL> alter system flush shared_pool;



System altered.





SQL> exec :n := 7698;



PL/SQL procedure successfully completed.



SQL> select * from emp where empno = :n;



     EMPNO ENAME      JOB	       MGR HIREDATE	    SAL       COMM

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

    DEPTNO DNAME

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

      7698 BLAKE      MANAGER	      7839 01-MAY-81	   2850

	30 UFO





SQL> exec :n := 7654;



PL/SQL procedure successfully completed.



SQL> select * from emp where empno = :n;



     EMPNO ENAME      JOB	       MGR HIREDATE	    SAL       COMM

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

    DEPTNO DNAME

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

      7654 MARTIN     SALESMAN	      7698 28-SEP-81	   1250       1400

	30 UFO







查看执行情况:

SQL> select sql_text,sql_id,a.executions from v$sql a 

where a.parsing_schema_name='SCOTT'  2  ;



SQL_TEXT		       SQL_ID	     EXECUTIONS

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

select * from emp where empno  3vv0t64yn0wrm	      2

= :n



BEGIN :n := 7698; END;	       gp8mhcr67r352	      1

BEGIN :n := 7654; END;	       apkbvs4zq7cnh	      1



SQL> select a.sql_text,a.sql_id,a.executions,a.version_count from v$sqlarea a where sql_id='3vv0t64yn0wrm';



SQL_TEXT		       SQL_ID	     EXECUTIONS VERSION_COUNT

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

select * from emp where empno  3vv0t64yn0wrm	      3 	    1

= :n





SQL> 

select a.sql_text,a.sql_id,a.executions,a.child_number from v$sql a where sql_id='3vv0t64yn0wrm';SQL> 



SQL_TEXT		       SQL_ID	     EXECUTIONS CHILD_NUMBER

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

select * from emp where empno  3vv0t64yn0wrm	      3 	   0

= :n



说明关闭绑定变量窥探,不会影响SQL语句的共享,关闭绑定变量窥探,Oracle就不能利用直方图信息了。



继续测试关闭绑定变量窥探,对Oracle执行计划的影响?



先打开绑定变量窥探:

SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

 FROM SYS.x$ksppi x, SYS.x$ksppcv y

 WHERE x.inst_id = USERENV ('Instance')

 AND y.inst_id = USERENV ('Instance')

 AND x.indx = y.indx

 AND x.ksppinm LIKE '%&par%';  2    3    4    5    6  

Enter value for par: peek_user

old   6:  AND x.ksppinm LIKE '%&par%'

new   6:  AND x.ksppinm LIKE '%peek_user%'



NAME

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

VALUE

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

DESCRIB

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

_optim_peek_user_binds

TRUE

enable peeking of user binds





SQL> begin

  2  for i in 1 .. 10000

  3  loop

  4  insert into test values(1,'a1'||i);

  5  commit;

  6  end loop; 

  7  end;

  8  /



SQL> insert  into test values(2,'a');



1 row created.



SQL> commit;



Commit complete.



SQL> select id,count(*) from test

  2  group by id;



	ID   COUNT(*)

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

	 1	10000

	 2	    1





SQL> BEGIN

  DBMS_STATS.GATHER_TABLE_STATS(ownname          => 'TEST',

                                tabname          => 'TEST',

                                estimate_percent => 100,

                                method_opt       => 'for all columns size skewonly',

                                no_invalidate    => FALSE,

                                degree           => 8,

                                cascade          => TRUE);

END;

  2    3    4    5    6    7    8    9   10  

 11  /



PL/SQL procedure successfully completed.



SQL> variable n number;

SQL> exec :n := 2;



PL/SQL procedure successfully completed.



SQL> select * from test where id = :n;



	ID NAME

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

	 2 a



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



PLAN_TABLE_OUTPUT

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



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

SQL_ID	14nw6f8vtgsz7, child number 0

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

select * from test where id = :n



Plan hash value: 2624864549



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

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

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

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

|   1 |  TABLE ACCESS BY INDEX ROWID| TEST	|     1 |    14 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN	    | TEST_IDX1 |     1 |	|     1   (0)| 00:00:01 |

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



Predicate Information (identified by operation id):

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



   2 - access("ID"=:N)





19 rows selected.

返回一条记录走的索引扫描







SQL> exec :n := 1;



PL/SQL procedure successfully completed.



SQL> select * from test where id = :n;



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



PLAN_TABLE_OUTPUT

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



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

SQL_ID	14nw6f8vtgsz7, child number 0

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

select * from test where id = :n



Plan hash value: 2624864549



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

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

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

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

|   1 |  TABLE ACCESS BY INDEX ROWID| TEST	|     1 |    14 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN	    | TEST_IDX1 |     1 |	|     1   (0)| 00:00:01 |

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



Predicate Information (identified by operation id):

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



   2 - access("ID"=:N)





19 rows selected.



走的还是索引扫描,充分说明Oracle在处理带有绑定变量的SQL时候,只会在硬解析的时候才会“窥探”一下SQL中绑定变量的值,然后会根据窥探到的值来决定整个SQL的执行计划



。





关闭绑定变量窥探:



SQL> alter system  set "_optim_peek_user_binds"=FALSE;



System altered.



SQL> alter system flush shared_pool;



System altered.



SQL> variable n number;

SQL> exec :n := 2;



PL/SQL procedure successfully completed.



SQL> select * from test where  id = :n;



	ID NAME

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

	 2 a



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



PLAN_TABLE_OUTPUT

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



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

SQL_ID	9tcmwpk23vu2y, child number 0

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

select * from test where  id = :n



Plan hash value: 1357081020



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

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

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

|   0 | SELECT STATEMENT  |	 |	 |	 |     9 (100)| 	 |

|*  1 |  TABLE ACCESS FULL| TEST |  5001 | 70014 |     9   (0)| 00:00:01 |

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



Predicate Information (identified by operation id):

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



   1 - filter("ID"=:N)





18 rows selected.



此时走了全表扫描,由于关闭了绑定变量窥探,无法利用直方图信息。





结论;

  (1)不绑定变量的情况下对于列倾斜严重的情况,直方图可以提供最好的数据分布参考



  (2)绑定变量窥视的情况下 可以利用到直方图,但是11g adaptive cursor sharing之前无法区别绑定敏感游标和非敏感游标



  (3)不窥视绑定变量的情况下虽然加载直方图信息,但实际计算cardinality不参考HISTOGRAM





开始绑定变量:使用直方图信息,然后会根据窥探到的值来决定整个SQL的执行计划。



不开始绑定变量:不使用直方图信息,Oracle不知道数据的分布情况



无论是否开始绑定变量窥探都不影响SQL语句共享




 

你可能感兴趣的:(绑定变量)