97
All About Binds Thomas Kyte

All About Binds

Embed Size (px)

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

Citation preview

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