all about binds

97
All About Binds Thomas Kyte

Upload: caldwell-mcclain

Post on 02-Jan-2016

43 views

Category:

Documents


2 download

DESCRIPTION

All About Binds. Thomas Kyte. It’s. All About Binds. Agenda. Performance Is it just about sharing SQL (or is this really a parsing talk in disguise) Scalability Security Do I always want to bind? What is bind variable peeking? Is it good or evil in disguise or a bit of both? - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: All About Binds

All About Binds

Thomas Kyte

Page 2: All About Binds

All About Binds

It’s

Page 3: All About Binds

Agenda

• Performance– Is it just about sharing SQL (or is this really a parsing talk in disguise)

• Scalability • Security• Do I always want to bind? • What is bind variable peeking?

– Is it good or evil in disguise or a bit of both?

• I’m binding, but it isn’t sharing – what’s up with that?• So the developers don't bind is cursor_sharing = force/similar

appropriate system wide?• What is the real difference between cursor_sharing =

force/similar and which should we use under what circumstances?

Page 4: All About Binds

Performance

• What is involved in a Parse– The “conventional” parse – syntax, semantic check– Optimization (can you spell C.P.U…)– Row Source Generation

• And then we can finally execute it• Conventional parse is fairly lightweight

– But it is called a “shared” pool, not “your” pool– Shared data structures have to be protected

• Optimization can be avoided• Row Source Generation can be avoided

Bind01.sql

Page 5: All About Binds

ops$tkyte%ORA11GR2> create table t ( x int primary key );

Table created.

ops$tkyte%ORA11GR2> create table parse_stats 2 as 3 select a.name, b.value, cast( null as number ) run1, cast(null as number) run2 4 from v$statname a, v$mystat b 5 where a.statistic# = b.statistic# 6 and a.name like 'parse%';

Table created.

sqlplus

Page 6: All About Binds

ops$tkyte%ORA11GR2> declare 2 l_cursor sys_refcursor; 3 begin 4 for i in 1 .. 10000 5 loop 6 open l_cursor for 'select /* nobind */ * from t where x = ' || i; 7 close l_cursor; 8 end loop; 9 end; 10 /

PL/SQL procedure successfully completed.

Elapsed: 00:00:11.04

sqlplus

Page 7: All About Binds

Bind01.sql

ops$tkyte%ORA11GR2> merge into parse_stats using ( select a.name, b.value new_val 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like 'parse%' ) s 5 on (parse_stats.name = s.name) when matched then update set run1 = new_val;

6 rows merged.

Elapsed: 00:00:00.15

sqlplus

Page 8: All About Binds

Bind01.sql

ops$tkyte%ORA11GR2> declare 2 l_cursor sys_refcursor; 3 begin 4 for i in 1 .. 10000 5 loop 6 open l_cursor for 'select /* bind */ * from t where x = :x' using i; 7 close l_cursor; 8 end loop; 9 end; 10 /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.73

sqlplus

Page 9: All About Binds

Bind01.sql

ops$tkyte%ORA11GR2> merge into parse_stats using ( select a.name, b.value new_val 2 from v$statname a, v$mystat b 3 where a.statistic# = b.statistic# 4 and a.name like 'parse%' ) s 5 on (parse_stats.name = s.name) when matched then update set run2 = new_val;

6 rows merged.

Elapsed: 00:00:00.01

sqlplus

Page 10: All About Binds

Bind01.sql

ops$tkyte%ORA11GR2> select name, run1, run2, 2 decode( run1, 0, null, 3 to_char(run2/run1*100,'9,999.00') || ' %' ) run2_pct_of_run1 4 from ( 5 select name, run1-value run1, run2-run1 run2 6 from parse_stats 7 ) 8 /

NAME RUN1 RUN2 RUN2_PCT_OF------------------------------ ---------- ---------- -----------parse time cpu 271 5 1.85 %parse time elapsed 278 9 3.24 %parse count (total) 10078 10018 99.40 %parse count (hard) 10014 3 .03 %parse count (failures) 0 0parse count (describe) 0 0

6 rows selected.

sqlplus

Page 11: All About Binds

Performance

• Wonder if it might affect memory utilization?• Strange that count(*) is so low for that first query

isn’t it.• Unfortunate that sum(sharable_mem) is so high

(and remember, it really is many times that amount)

Bind02.sql

Page 12: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select count(*), to_char(sum(sharable_mem),'999,999,999') sm, 2 to_char(sum(sharable_mem)/ decode( count(*), 0, to_number(null), count(*) ), '999,999,999' ) per_stmt 3 from v$sql 4 where sql_text like 'select /* nobind */ * from t where x = %';

COUNT(*) SM PER_STMT---------- ------------ ------------ 57 781,917 13,718

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> select count(*), to_char(sum(sharable_mem),'999,999,999') sm 2 from v$sql 3 where sql_text = 'select /* bind */ * from t where x = :x';

COUNT(*) SM---------- ------------ 1 13,856

Page 13: All About Binds

sqlplus

ops$tkyte%ORA11GR2> declare 2 l_stmt long := 'select /*+ RULE */ * from t where x in ( 1'; 3 l_rec t%rowtype; 4 l_cursor sys_refcursor; 5 begin 6 for i in 2 .. 1000 7 loop 8 l_stmt := l_stmt || ', ' || i; 9 end loop; 10 l_stmt := l_stmt || ' ) or x in ( 1'; 11 for i in 1002 .. 2000 12 loop 13 l_stmt := l_stmt || ', ' || i; 14 end loop; 15 open l_cursor for l_stmt || ' )'; 16 fetch l_cursor into l_rec; 17 close l_cursor; 18 end; 19 /

PL/SQL procedure successfully completed.

Page 14: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select count(*), to_char(sum(sharable_mem),'999,999,999') sm 2 from v$sql 3 where sql_text like 'select /*+ RULE */ * from t where x in ( 1%';

COUNT(*) SM---------- ------------ 1 2,597,091

Page 15: All About Binds

Scalability

• But it runs fast enough and I’ll buy more memory

• Does it really?– Run bind03.sql– Review multiuser.sql– Findings coming right up…

ops$tkyte@ORA10GR1> select 11/10000 from dual; 11/10000---------- .0011

Page 16: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create table t ( x int primary key );

Table created.

ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats( user, 'T' );

PL/SQL procedure successfully completed.

Page 17: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create or replace procedure nobind 2 as 3 l_cursor sys_refcursor; 4 begin 5 for i in 1 .. 2000 6 loop 7 open l_cursor for 'select /* nobind */ * from t where x = ' || i; 8 close l_cursor; 9 end loop; 10 end; 11 /

Procedure created.

Page 18: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create or replace procedure bind 2 as 3 l_cursor sys_refcursor; 4 begin 5 for i in 1 .. 2000 6 loop 7 open l_cursor for 'select /* bind */ * from t where x = :x' using i; 8 close l_cursor; 9 end loop; 10 end; 11 /

Procedure created.

Page 19: All About Binds

sqlplus

ops$tkyte%ORA11GR2> exec runstats_pkg.rs_start

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> exec nobind

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> exec runstats_pkg.rs_middle

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> exec bind

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> exec runstats_pkg.rs_stop(10000)Run1 ran in 68 hsecsRun2 ran in 8 hsecsrun 1 ran in 850% of the time

Page 20: All About Binds

sqlplus

Name Run1 Run2 DiffLATCH.kks stats 10,831 33 -10,798LATCH.shared pool simulator 15,068 63 -15,005LATCH.row cache objects 48,470 191 -48,279STAT...session uga memory max 123,452 65,512 -57,940STAT...session uga memory 65,512 0 -65,512STAT...session pga memory max 131,072 65,536 -65,536LATCH.shared pool 87,428 327 -87,101STAT...session pga memory 65,536 -65,536 -131,072

Run1 latches total versus runs -- difference and pctRun1 Run2 Diff Pct171,431 1,150 -170,281 14,907.04%

PL/SQL procedure successfully completed.

Page 21: All About Binds

Security

• Google sql injection• Funny thing happened during my last column

create or replace procedure set_udump (p_udump in varchar2)asbegin execute immediate 'alter system set user_dump_dest = '''||p_udump||''' scope=memory';end;/

Page 22: All About Binds

Security

• Google sql injection• Funny thing happened during my last column

create or replace procedure set_udump (p_udump in varchar2)asbegin execute immediate 'alter system set user_dump_dest = '''||p_udump||''' scope=memory';end;/

begin set_udump('C:\ORA4\admin\ora4\udump2'' scope=memory utl_file_dir=''*'' scope=spfile user_dump_dest=''C:\ORA4\admin\ora4\udump2'); end;

Page 23: All About Binds

Security

• Google sql injection• Funny thing happened during my last column

create or replace procedure set_udump (p_udump in varchar2)asbegin if ( p_udump NOT LIKE '%=%' ) then execute immediate 'alter system set user_dump_dest = '''||p_udump||''' scope=memory'; else raise_application_error(-20000,'Sorry, but for safety reasons this procedure does not allow "=" in the parameter value'); end if;end; inj.sql

Page 24: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create or replace procedure inj( p_date in date ) 2 as 3 l_rec all_users%rowtype; 4 c sys_refcursor; 5 l_query long; 6 begin 7 l_query := ' 8 select * 9 from all_users 10 where created = ''' ||p_date ||''''; 11 12 dbms_output.put_line( l_query ); 13 open c for l_query; 14 15 for i in 1 .. 5 16 loop 17 fetch c into l_rec; 18 exit when c%notfound; 19 dbms_output.put_line( l_rec.username || '.....' ); 20 end loop; 21 close c; 22 end; 23 /Procedure created.

Page 25: All About Binds

sqlplus

ops$tkyte%ORA11GR2> exec inj( sysdate )

select * from all_users where created = '25-OCT-10'

PL/SQL procedure successfully completed.

Page 26: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set 2 nls_date_format = 'dd-mon-yyyy"'' or ''a'' = ''a"';

Session altered.

Page 27: All About Binds

sqlplus

ops$tkyte%ORA11GR2> exec inj( sysdate )

select * from all_users where created = '25-oct-2010' or 'a' = 'a'C.....B.....A.....FB_DEMO.....BIG_TABLE.....

PL/SQL procedure successfully completed.

Page 28: All About Binds

Do I always want to bind?

• Always say “Never say Never”• Never say “Always”• I always say…• You do not want to

– Over Bind– Always Bind– Why….

Page 29: All About Binds

Do I always want to bind?

• Over Binding– Compulsive disorder to eradicate all literals in SQL– Brought on by taking good advice to an illogical

extreme

– Do we need to bind those?– Might it be a bad thing to bind those?

Begin for x in ( select object_name from user_objects where object_type in ( ‘TABLE’, ‘INDEX’ )) loop …

Page 30: All About Binds

Do I always want to bind?

• Always Binding– Data warehouse – no way.– When you run queries per second, yes.– When you run queries that take seconds, maybe,

maybe no.• Consider the frequency of the query

o 5,000 users running reports. Bindo 50 users data mining. No Bindo OLTP. Bindo End of month report. Maybe No Bind.o Common Sense, it is all about math

Page 31: All About Binds

Bind Variable Peeking

• It is good or pure evil in disguise (neither of course)• Introduced in 9i Release 1• Makes the first hard parse of:

• Optimize as if you submitted:

• What are the assumptions then by the implementer of this feature.

Select * from emp where empno = :X;

Select * from emp where empno = 1234;

bvp01.sql

Page 32: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create table t 2 as 3 select 99 id, a.* 4 from stage a 5 where rownum <= 20000;

Table created.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> update t set id = 1 where rownum = 1;

1 row updated.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> create index t_idx on t(id);

Index created.

Page 33: All About Binds

sqlplus

ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats 3 ( user, 'T', 4 method_opt=>'for all indexed columns size 254', 5 estimate_percent => 100, 6 cascade=>TRUE ); 7 end; 8 /

PL/SQL procedure successfully completed.

Page 34: All About Binds

sqlplusops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select count(object_type) from t where id = 1;

Execution Plan----------------------------------------------------------Plan hash value: 1789076273

--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 14 | 2 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 14 | | || 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 14 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------

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

3 - access("ID"=1)

ops$tkyte%ORA11GR2> set autotrace off

Page 35: All About Binds

sqlplusops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select count(object_type) from t where id = 99;

Execution Plan----------------------------------------------------------Plan hash value: 2966233522

---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 14 | 82 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 14 | | ||* 2 | TABLE ACCESS FULL| T | 19999 | 273K| 82 (0)| 00:00:01 |---------------------------------------------------------------------------

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

2 - filter("ID"=99)

ops$tkyte%ORA11GR2> set autotrace off

Page 36: All About Binds

sqlplusops$tkyte%ORA11GR2> variable n numberops$tkyte%ORA11GR2> exec :n := 1PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> explain plan for 2 select count(object_type) from t n_is_1_first where id = :n;Explained.

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT--------------------Plan hash value: 2966233522---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 14 | 82 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 14 | | ||* 2 | TABLE ACCESS FULL| T | 10000 | 136K| 82 (0)| 00:00:01 |---------------------------------------------------------------------------

Predicate Information (identified by operation id):--------------------------------------------------- 2 - filter("ID"=TO_NUMBER(:N))

14 rows selected.

Page 37: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context forever, level 12';

Session altered.

ops$tkyte%ORA11GR2> select count(object_type) from t n_is_1_first where id = :n;

COUNT(OBJECT_TYPE)------------------ 1

Page 38: All About Binds

sqlplus

ops$tkyte%ORA11GR2> exec :n := 99

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select count(object_type) from t n_is_1_first where id = :n;

COUNT(OBJECT_TYPE)------------------ 19999

Page 39: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select count(object_type) from t n_is_99_first where id = :n;

COUNT(OBJECT_TYPE)------------------ 19999

Page 40: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select count(object_type) from t n_is_99_first where id = :n;

COUNT(OBJECT_TYPE)------------------ 1

Page 41: All About Binds

sqlplusselect count(object_type)from t n_is_1_first where id = :n

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

Misses in library cache during parse: 1Misses in library cache during execute: 1Optimizer mode: ALL_ROWSParsing user id: 211 (OPS$TKYTE)

Rows Row Source Operation------- --------------------------------------------------- 1 SORT AGGREGATE (cr=3 pr=0 pw=0 time=0 us) 1 TABLE ACCESS BY INDEX ROWID T (cr=3 pr=0 pw=0 time=0 us cost=2 size=14 card=1) 1 INDEX RANGE SCAN T_IDX (cr=2 pr=0 pw=0 time=0 us cost=1 size=0 card=1)(object id 88040)

Rows Execution Plan------- --------------------------------------------------- 0 SELECT STATEMENT MODE: ALL_ROWS 1 SORT (AGGREGATE) 1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T' (TABLE)

Page 42: All About Binds

sqlplusselect count(object_type) from t n_is_1_first where id = :n

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

Misses in library cache during parse: 0Optimizer mode: ALL_ROWSParsing user id: 211 (OPS$TKYTE)

Rows Row Source Operation------- --------------------------------------------------- 1 SORT AGGREGATE (cr=322 pr=0 pw=0 time=0 us) 19999 TABLE ACCESS BY INDEX ROWID T (cr=322 pr=0 pw=0 time=76043 us cost=2 size=14 card=1) 19999 INDEX RANGE SCAN T_IDX (cr=41 pr=0 pw=0 time=25984 us cost=1 size=0 card=1)(object id 88040)

Rows Execution Plan------- --------------------------------------------------- 0 SELECT STATEMENT MODE: ALL_ROWS 1 SORT (AGGREGATE) 19999 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T' (TABLE)

Page 43: All About Binds

sqlplusselect count(object_type)from t n_is_99_first where id = :n

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

Misses in library cache during parse: 1Misses in library cache during execute: 1Optimizer mode: ALL_ROWSParsing user id: 211 (OPS$TKYTE)

Rows Row Source Operation------- --------------------------------------------------- 1 SORT AGGREGATE (cr=285 pr=0 pw=0 time=0 us) 19999 TABLE ACCESS FULL T (cr=285 pr=0 pw=0 time=24838 us cost=82 size=279986 card=19999)

Rows Execution Plan------- --------------------------------------------------- 0 SELECT STATEMENT MODE: ALL_ROWS 1 SORT (AGGREGATE) 19999 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T' (TABLE)

Page 44: All About Binds

sqlplusselect count(object_type)from t n_is_99_first where id = :n

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

Misses in library cache during parse: 0Optimizer mode: ALL_ROWSParsing user id: 211 (OPS$TKYTE)

Rows Row Source Operation------- --------------------------------------------------- 1 SORT AGGREGATE (cr=285 pr=0 pw=0 time=0 us) 1 TABLE ACCESS FULL T (cr=285 pr=0 pw=0 time=0 us cost=82 size=279986 card=19999)

Rows Execution Plan------- --------------------------------------------------- 0 SELECT STATEMENT MODE: ALL_ROWS 1 SORT (AGGREGATE) 1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T' (TABLE)

Page 45: All About Binds

Bind Variable Peeking

• Adaptive Cursor Sharing– New in 11gR1– Will help solve most bind variable peeking issues– Works currently with equality and range operations (but

not “like” predicates)

bvp03.sql

Page 46: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create table t 2 as 3 select 99 id, a.* 4 from stage a 5 where rownum <= 20000;

Table created.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> update t set id = 1 where rownum = 1;

1 row updated.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> create index t_idx on t(id);

Index created.

Page 47: All About Binds

sqlplus

ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats 3 ( user, 'T', 4 method_opt=>'for all indexed columns size 254', 5 estimate_percent => 100, 6 cascade=>TRUE ); 7 end; 8 /

PL/SQL procedure successfully completed.

Page 48: All About Binds

sqlplusops$tkyte%ORA11GR2> exec :n := 1;PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select /*BVP03*/ count(subobject_name) from t where id = :n;

COUNT(SUBOBJECT_NAME)--------------------- 0

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT-----------------------SQL_ID 4un62u0uttg6u, child number 0-------------------------------------select /*BVP03*/ count(subobject_name) from t where id = :n

Plan hash value: 1789076273--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 2 (100)| || 1 | SORT AGGREGATE | | 1 | 20 | | || 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 20 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):--------------------------------------------------- 3 - access("ID"=:N)

20 rows selected.

Page 49: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select child_number, executions, buffer_gets, 2 is_bind_sensitive, is_bind_aware 3 from v$sql 4 where sql_text like 'select /*BVP03*/ %';

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS_BIND_SENSITIVE IS_BIND_AWARE------------ ---------- ----------- ------------------ --------------- 0 1 3 Y N

Page 50: All About Binds

sqlplusops$tkyte%ORA11GR2> exec :n := 99;PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select /*BVP03*/ count(subobject_name) from t where id = :n;

COUNT(SUBOBJECT_NAME)--------------------- 118

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT-----------------------------------------SQL_ID 4un62u0uttg6u, child number 0-------------------------------------select /*BVP03*/ count(subobject_name) from t where id = :n

Plan hash value: 1789076273--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 2 (100)| || 1 | SORT AGGREGATE | | 1 | 20 | | || 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 20 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):--------------------------------------------------- 3 - access("ID"=:N)

20 rows selected.

Page 51: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select child_number, executions, buffer_gets, 2 is_bind_sensitive, is_bind_aware 3 from v$sql 4 where sql_text like 'select /*BVP03*/ %';

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS_BIND_SENSITIVE IS_BIND_AWARE------------ ---------- ----------- ------------------ --------------- 0 2 325 Y N

Page 52: All About Binds

sqlplusops$tkyte%ORA11GR2> select /*BVP03*/ count(subobject_name) from t where id = :n;

COUNT(SUBOBJECT_NAME)--------------------- 118

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT-------------------------SQL_ID 4un62u0uttg6u, child number 1-------------------------------------select /*BVP03*/ count(subobject_name) from t where id = :n

Plan hash value: 2966233522---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 82 (100)| || 1 | SORT AGGREGATE | | 1 | 20 | | ||* 2 | TABLE ACCESS FULL| T | 19999 | 390K| 82 (0)| 00:00:01 |---------------------------------------------------------------------------

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

2 - filter("ID"=:N)

19 rows selected.

Page 53: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select child_number, executions, buffer_gets, 2 is_bind_sensitive, is_bind_aware 3 from v$sql 4 where sql_text like 'select /*BVP03*/ %';

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS_BIND_SENSITIVE IS_BIND_AWARE------------ ---------- ----------- ------------------ --------------- 0 2 325 Y N 1 1 285 Y Y

Page 54: All About Binds

sqlplusops$tkyte%ORA11GR2> exec :n := 1PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select /*BVP03*/ count(subobject_name) from t where id = :n;

COUNT(SUBOBJECT_NAME)--------------------- 0

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT---------------------------SQL_ID 4un62u0uttg6u, child number 2-------------------------------------select /*BVP03*/ count(subobject_name) from t where id = :n

Plan hash value: 1789076273--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 2 (100)| || 1 | SORT AGGREGATE | | 1 | 20 | | || 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 20 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):--------------------------------------------------- 3 - access("ID"=:N)

20 rows selected.

Page 55: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select child_number, executions, buffer_gets, 2 is_bind_sensitive, is_bind_aware 3 from v$sql 4 where sql_text like 'select /*BVP03*/ %';

CHILD_NUMBER EXECUTIONS BUFFER_GETS IS_BIND_SENSITIVE IS_BIND_AWARE------------ ---------- ----------- ------------------ --------------- 0 2 325 Y N 1 1 285 Y Y 2 1 3 Y Y

Page 56: All About Binds

Bind Variable Peeking over time

• 8i and before– no peeking

• 9i, 10g – Peeking– First plan “wins”

• 11g and above– Adaptive Cursor Sharing

Page 57: All About Binds

Bind Variable Peeking• What can you do when those assumptions don’t hold true for

you in a specific case? – 11gR1 and above!!– Don’t bind that query, that is a possibility.

• Do the math… – Don’t use histograms

• Get the “general plan”• Consistent Plan, but typically not the “best” plan for all

– Use your domain knowledge• Input dates within the last month – use this query, else use that query• Codes less than 50 – use this query, else use that query• Status values of ‘A’, ‘M’ and ‘N’ …. Else….

– Cursor_sharing = similar– You can disable it – but that is like “don’t use histograms” in a

system that uses binds.

Page 58: All About Binds

I’m binding, but it isn’t sharing

• Many things can do that– Any environmental variables that affect the optimizer– Or security (this is why PLSQL rules)– Bind Type mismatch– Language– PLSQL compiler switches

• For example, lets tune with SQL_TRACE=TRUE• And Look deeper at “bind mismatches”• Desc v$sql_shared_cursor

tune.sqlBindmis.sql

Page 59: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set "_optimizer_extended_cursor_sharing_rel"=none;

Session altered.

ops$tkyte%ORA11GR2> create table t 2 as 3 select 99 id, a.* 4 from stage a 5 where rownum <= 20000;

Table created.

ops$tkyte%ORA11GR2> update t set id = 1 where rownum = 1;

1 row updated.

ops$tkyte%ORA11GR2> create index t_idx on t(id);

Index created.

Page 60: All About Binds

sqlplus

ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats 3 ( user, 'T', 4 method_opt => 'for all indexed columns size 254', 5 estimate_percent => 100, 6 cascade=> true); 7 end; 8 /

PL/SQL procedure successfully completed.

Page 61: All About Binds

sqlplusops$tkyte%ORA11GR2> variable n numberops$tkyte%ORA11GR2> exec :n := 99

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> set autotrace traceonly statisticsops$tkyte%ORA11GR2> select * from t where id = :n;

19999 rows selected.

Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 1601 consistent gets 0 physical reads 0 redo size 928023 bytes sent via SQL*Net to client 15082 bytes received via SQL*Net from client 1335 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 19999 rows processed

ops$tkyte%ORA11GR2> set autotrace off

Page 62: All About Binds

sqlplus

ops$tkyte%ORA11GR2> exec :n := 1

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> set autotrace traceonly statisticsops$tkyte%ORA11GR2> select * from t where id = :n;

Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 286 consistent gets 0 physical reads 0 redo size 1448 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

ops$tkyte%ORA11GR2> set autotrace off

Page 63: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context forever, level 12';

Session altered.

ops$tkyte%ORA11GR2> select * from t where id = :n;

Statistics---------------------------------------------------------- 1 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 1448 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

Page 64: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context off';

Session altered.

ops$tkyte%ORA11GR2> select * from t where id = :n;

Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 286 consistent gets 0 physical reads 0 redo size 1448 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

Page 65: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context forever, level 12';

Session altered.

ops$tkyte%ORA11GR2> select * from t where id = :n;

Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 1448 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

Page 66: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context off';

Session altered.

ops$tkyte%ORA11GR2> select * from t where id = :n;

Statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 286 consistent gets 0 physical reads 0 redo size 1448 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

Page 67: All About Binds

sqlplusops$tkyte%ORA11GR2> select parsing_user_id puid, parsing_schema_id psid, is_bind_aware, is_bind_sensitive, 2 address, child_address 3 from v$sql 4 where sql_text = 'select * from t where id = :n';

PUID PSID IS_BIND_AWARE IS_BIND_SENSITIVE ADDRESS CHILD_AD---------- ---------- --------------- ------------------ -------- -------- 211 211 N N 32448F98 2D55B0B0 211 211 N N 32448F98 3245FF8C

Page 68: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set "_optimizer_extended_cursor_sharing_rel"=simple;

Session altered.

Page 69: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create table t ( x varchar2(2000) );

Table created.

Page 70: All About Binds

sqlplus

ops$tkyte%ORA11GR2> declare 2 a varchar2(1) := 'x'; 3 b varchar2(100) := rpad('x',100,'x'); 4 c varchar2(500) := rpad('x',500,'x'); 5 d varchar2(1000) := rpad('x',1000,'x'); 6 begin 7 insert into t values(a); 8 insert into t values(b); 9 insert into t values(c); 10 insert into t values(d); 11 end; 12 /

PL/SQL procedure successfully completed.

Page 71: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select parsing_user_id puid, parsing_schema_id psid, 2 sql_text, address, child_address 3 from v$sql 4 where sql_text like 'INSERT%INTO%T%VALUES(%:B1%)' 5 /

PUID PSID SQL_TEXT ADDRESS CHILD_AD---------- ---------- ------------------------------ -------- -------- 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2D77BDF8 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 325BFA18 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2C284A44

Page 72: All About Binds

sqlplusops$tkyte%ORA11GR2> select * 2 from v$sql_shared_cursor 3 where address = '&ADDR' 4 /old 3: where address = '&ADDR'new 3: where address = '325F10B8'

SQL_ID ADDRESS CHILD_AD CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U T N F A I 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- - - - - - - - - - - - - - - - - - - - - - - - -9bay73nakuyw9 325F10B8 2D77BDF8 0 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 NN N N N N N N N N N N N N N N N N N N N N N N N N

9bay73nakuyw9 325F10B8 325BFA18 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 NN N N N N N N N N N N N N N N N N N N N N N N N Y

9bay73nakuyw9 325F10B8 2C284A44 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 NN N N N N N N N N N N N N N N N N N N N N N N N Y

Page 73: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select bind_mismatch, BIND_LENGTH_UPGRADEABLE 2 from v$sql_shared_cursor 3 where address = '&ADDR' 4 /old 3: where address = '&ADDR'new 3: where address = '325F10B8'

B B- -N NN YN Y

Page 74: All About Binds

sqlplus

ops$tkyte%ORA11GR2> declare 2 a varchar2(1) := 'x'; 3 b varchar2(10) := rpad('x',10,'x'); 4 c varchar2(20) := rpad('x',20,'x'); 5 d varchar2(30) := rpad('x',30,'x'); 6 begin 7 insert into t xxx values(a); 8 insert into t xxx values(b); 9 insert into t xxx values(c); 10 insert into t xxx values(d); 11 end; 12 /

PL/SQL procedure successfully completed.

Page 75: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select parsing_user_id puid, parsing_schema_id psid, 2 sql_text, address, child_address 3 from v$sql 4 where sql_text like 'INSERT%INTO%T%VALUES(%:B1%)' 5 /

PUID PSID SQL_TEXT ADDRESS CHILD_AD---------- ---------- ------------------------------ -------- -------- 211 211 INSERT INTO T XXX VALUES(:B1 ) 2D4C7DEC 2C33D5A4 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2D77BDF8 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 325BFA18 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2C284A44

Page 76: All About Binds

sqlplus

ops$tkyte%ORA11GR2> declare 2 a varchar2(1) := 'x'; 3 b varchar2(10) := rpad('x',10,'x'); 4 c varchar2(32) := rpad('x',32,'x'); 5 d varchar2(33) := rpad('x',33,'x'); 6 begin 7 insert into t yyy values(a); 8 insert into t yyy values(b); 9 insert into t yyy values(c); 10 insert into t yyy values(d); 11 end; 12 /

PL/SQL procedure successfully completed.

Page 77: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select parsing_user_id puid, parsing_schema_id psid, 2 sql_text, address, child_address 3 from v$sql 4 where sql_text like 'INSERT%INTO%T%VALUES(%:B1%)' 5 /

PUID PSID SQL_TEXT ADDRESS CHILD_AD---------- ---------- ------------------------------ -------- -------- 211 211 INSERT INTO T YYY VALUES(:B1 ) 2D55EF40 2C1E7E8C 211 211 INSERT INTO T YYY VALUES(:B1 ) 2D55EF40 32474080 211 211 INSERT INTO T XXX VALUES(:B1 ) 2D4C7DEC 2C33D5A4 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2D77BDF8 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 325BFA18 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2C284A44

6 rows selected.

Page 78: All About Binds

sqlplus

ops$tkyte%ORA11GR2> declare 2 a varchar2(1) := 'x'; 3 b varchar2(100) := rpad('x',100,'x'); 4 c varchar2(500) := rpad('x',500,'x'); 5 d varchar2(1000) := rpad('x',1000,'x'); 6 begin 7 insert into t zzz values(d); 8 insert into t zzz values(c); 9 insert into t zzz values(b); 10 insert into t zzz values(a); 11 end; 12 /

PL/SQL procedure successfully completed.

Page 79: All About Binds

sqlplus

ops$tkyte%ORA11GR2> select parsing_user_id puid, parsing_schema_id psid, 2 sql_text, address, child_address 3 from v$sql 4 where sql_text like 'INSERT%INTO%T%VALUES(%:B1%)' 5 /

PUID PSID SQL_TEXT ADDRESS CHILD_AD---------- ---------- ------------------------------ -------- -------- 211 211 INSERT INTO T YYY VALUES(:B1 ) 2D55EF40 2C1E7E8C 211 211 INSERT INTO T YYY VALUES(:B1 ) 2D55EF40 32474080 211 211 INSERT INTO T XXX VALUES(:B1 ) 2D4C7DEC 2C33D5A4 211 211 INSERT INTO T ZZZ VALUES(:B1 ) 2D5ECF98 2D52AFD0 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2D77BDF8 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 325BFA18 211 211 INSERT INTO T VALUES(:B1 ) 325F10B8 2C284A44

7 rows selected.

Page 80: All About Binds

Cursor Sharing

• So the developers don't bind is cursor_sharing = force/similar appropriate system wide?

No

Page 81: All About Binds

Cursor Sharing

• Negatively Impacts Well Written Applications– They run slower even if plans do not change– We just did bind variable peeking, so we know about

• Over binding (this is over binding defined)• Always binding (this is always binding defined)

– Possible plan changes• Optimizer has less information, doesn’t have the facts

– Behavior Changes• Don’t know column widths anymore• Don’t know scale/precision anymore

cs01.sql

Page 82: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set cursor_sharing=exact;

Session altered.

ops$tkyte%ORA11GR2> create table t 2 as 3 select * 4 from all_users 5 where rownum = 1;

Table created.

Page 83: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set cursor_sharing=exact;

Session altered.

ops$tkyte%ORA11GR2> select substr(username,1,10) uname, 2 to_char(user_id,'999,999') u_id, 3 to_char(created,'Dy Mon DD, YYYY' ) created 4 from t cs_exact;

UNAME U_ID CREATED---------- -------- ----------------SYS 0 Thu Aug 13, 2009

Page 84: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set cursor_sharing=force;

Session altered.

ops$tkyte%ORA11GR2> select substr(username,1,10) uname, 2 to_char(user_id,'999,999') u_id, 3 to_char(created,'Dy Mon DD, YYYY' ) created 4 from t cs_force;

UNAME------------------------------U_ID-------------------------------------------------------------------------------------------------------------------------CREATED---------------------------------------------------------------------------SYS 0Thu Aug 13, 2009

Page 85: All About Binds

sqlplusops$tkyte%ORA11GR2> alter session set cursor_sharing=exact;

Session altered.

ops$tkyte%ORA11GR2> column sql_text format a80ops$tkyte%ORA11GR2> select sql_text 2 from v$sql 3 where sql_text like 'select substr(username%';

SQL_TEXT--------------------------------------------------------------------------------select substr(username,1,10) uname, to_char(user_id,'999,999') u_id, to_char(created,'Dy Mon DD, YYYY' ) created from t cs_exact

select substr(username,:"SYS_B_0",:"SYS_B_1") uname, to_char(user_id,:"SYS_B_2") u_id, to_char(created,:"SYS_B_3" ) created from t cs_force

Page 86: All About Binds

Force/Similar

• Force is just that– All literals, without any regard to anything, will be

replaced with binds– 10g and before - There will be probably one plan

generated (all things considered the same! Remember v$sql_shared_cursor)

• Consider the bind variable peeking implicationso Cold start, first query is id=99o Cold start, first query is id=1o Bouncing the database is my tuning tool?

– But, things change… 11gR1 and up

Page 87: All About Binds

Force/Similar

• Similar– When replacing the bind with a literal (reversed purposely)

could change the plan… – Multiple child cursors will be developed– Each can have it’s own unique plan– Optimization will use the “best” plan– Is this better than force?

• Depends• More child cursors• Longer code path

– But is does solve a little more of the problem.

similar.sql

Page 88: All About Binds

sqlplus

ops$tkyte%ORA11GR2> create table emp as select * from scott.emp;Table created.

ops$tkyte%ORA11GR2> update emp set deptno = 99;

14 rows updated.

ops$tkyte%ORA11GR2> begin 2 for i in 1 .. 11 3 loop 4 insert /*+ append */ into emp select * from emp; 5 commit; 6 end loop; 7 end; 8 /

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> select count(*) from emp;

COUNT(*)---------- 28672

Page 89: All About Binds

sqlplus

ops$tkyte%ORA11GR2> update emp set deptno = 1 where rownum = 1;

1 row updated.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> create index dept_idx on emp(deptno);

Index created.

ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats 3 ( user, 'EMP', 4 method_opt=>'for all indexed columns', 5 estimate_percent => 100, 6 cascade=>true ); 7 end; 8 /

PL/SQL procedure successfully completed.

Page 90: All About Binds

sqlplusops$tkyte%ORA11GR2> select count(empno) from emp where deptno = 99;

Execution Plan----------------------------------------------------------Plan hash value: 2083865914

---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 16 | 53 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 16 | | ||* 2 | TABLE ACCESS FULL| EMP | 28671 | 447K| 53 (0)| 00:00:01 |---------------------------------------------------------------------------

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

2 - filter("DEPTNO"=99)

Page 91: All About Binds

sqlplusops$tkyte%ORA11GR2> select count(empno) from emp where deptno = 1;

Execution Plan----------------------------------------------------------Plan hash value: 237848182

-----------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 16 | 2 (0)| 00:00:01 || 1 | SORT AGGREGATE | | 1 | 16 | | || 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 16 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | DEPT_IDX | 1 | | 1 (0)| 00:00:01 |-----------------------------------------------------------------------------------------

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

3 - access("DEPTNO"=1)

Page 92: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set events '10046 trace name context forever, level 12';

Session altered.

ops$tkyte%ORA11GR2> alter session set cursor_sharing=similar;

Session altered.

Page 93: All About Binds

sqlplusops$tkyte%ORA11GR2> select count(empno) from emp CSS where deptno = 1;COUNT(EMPNO)------------ 1

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT-------------------------------------------------------------------------------------------------------------------------SQL_ID 93pjrvfdz49m5, child number 0-------------------------------------select count(empno) from emp CSS where deptno = :"SYS_B_0"

Plan hash value: 237848182

-----------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 2 (100)| || 1 | SORT AGGREGATE | | 1 | 16 | | || 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 16 | 2 (0)| 00:00:01 ||* 3 | INDEX RANGE SCAN | DEPT_IDX | 1 | | 1 (0)| 00:00:01 |-----------------------------------------------------------------------------------------

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

3 - access("DEPTNO"=:SYS_B_0)

20 rows selected.

Page 94: All About Binds

sqlplusops$tkyte%ORA11GR2> select count(empno) from emp CSS where deptno = 99;COUNT(EMPNO)------------ 28671

ops$tkyte%ORA11GR2> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT-------------------------------------------------------------------------------------------------------------------------SQL_ID 93pjrvfdz49m5, child number 1-------------------------------------select count(empno) from emp CSS where deptno = :"SYS_B_0"

Plan hash value: 2083865914

---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 53 (100)| || 1 | SORT AGGREGATE | | 1 | 16 | | ||* 2 | TABLE ACCESS FULL| EMP | 28671 | 447K| 53 (0)| 00:00:01 |---------------------------------------------------------------------------

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

2 - filter("DEPTNO"=:SYS_B_0)

19 rows selected.

Page 95: All About Binds

sqlplus

ops$tkyte%ORA11GR2> alter session set cursor_sharing=exact;

Session altered.

ops$tkyte%ORA11GR2> select sql_text, is_bind_aware, is_bind_sensitive from v$sql 2 where sql_text like 'select count(empno) from emp CSS where deptno =%';

SQL_TEXT IS_BIND_AWARE IS_BIND_SENSITIVE---------------------------------------- --------------- ------------------select count(empno) from emp CSS where d N Yeptno = :"SYS_B_0"

select count(empno) from emp CSS where d N Yeptno = :"SYS_B_0"

Page 96: All About Binds

Force/Similar• In Short, in 10g and before just say

NoTo setting at the system level, this is an application level bug “workaround until we get it fixed for real” tool

Page 97: All About Binds

Questions