cursor_sharing similar is a very aggressive sloppy adaptive cursor sharing. That is one way to think of it.
cursor sharing similar will look at the rewritten sql and if ANY of the binds are possibly "not safe to share", it will set up a separate child cursor for every query input. For example:
ops$tkyte%ORA11GR1> /*
ops$tkyte%ORA11GR1> drop table t;
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> create table t
ops$tkyte%ORA11GR1> as
ops$tkyte%ORA11GR1> select case when rownum = 1 then 1 else 99 end id,
ops$tkyte%ORA11GR1> all_objects.*
ops$tkyte%ORA11GR1> from all_objects
ops$tkyte%ORA11GR1> /
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> create index t_idx on t(id);
ops$tkyte%ORA11GR1> exec dbms_stats.gather_table_stats( user, 'T', method_opt=>'for all indexed columns', estimate_percent=>100 );
ops$tkyte%ORA11GR1> */
so, some very skewed data - and we have statistics that show that ID=1 should use an index and ID=99 should full scan...
we use cursor sharing with inputs of 1, 2, 3, 4, and 99 - five sets of inputs...
ops$tkyte%ORA11GR1> alter system flush shared_pool;
System altered.
ops$tkyte%ORA11GR1> alter session set cursor_sharing=similar;
Session altered.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 1;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 99;
COUNT(SUBOBJECT_NAME)
---------------------
535
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 2;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 3;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 4;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 1;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 99;
COUNT(SUBOBJECT_NAME)
---------------------
535
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 2;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 3;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = 4;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1>
ops$tkyte%ORA11GR1> select sql_id, sql_text, is_bind_aware, is_bind_sensitive from v$sql where sql_text like 'select count(subobject_name) from t where id = %';
SQL_ID SQL_TEXT I I
------------- -------------------------------------------------- - -
b1yda827jbjw9 select count(subobject_name) from t where id = :"S N Y
YS_B_0"
b1yda827jbjw9 select count(subobject_name) from t where id = :"S N Y
YS_B_0"
b1yda827jbjw9 select count(subobject_name) from t where id = :"S N Y
YS_B_0"
b1yda827jbjw9 select count(subobject_name) from t where id = :"S N Y
YS_B_0"
b1yda827jbjw9 select count(subobject_name) from t where id = :"S N Y
YS_B_0"
see, five inputs, five plans in v$sql - in fact if you said "id = 20", it would add another, "id = 25", add another and so on - every unique set of binds against id will generate yet another plan.
adaptive cursor sharing will be different. Where as similar causes a new plan IMMEDIATELY upon seeing a different bind variable against ID - similar will wait - to see if it causes a problem. And even then, it'll only generate as many plans as it needs:
ops$tkyte%ORA11GR1> alter session set cursor_sharing=exact;
Session altered.
ops$tkyte%ORA11GR1> variable x number
ops$tkyte%ORA11GR1> exec :x := 1
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 99
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
535
ops$tkyte%ORA11GR1> exec :x := 2
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 3
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 4
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 1
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 99
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
535
ops$tkyte%ORA11GR1> exec :x := 2
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 3
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> exec :x := 4
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR1> select count(subobject_name) from t where id = :x;
COUNT(SUBOBJECT_NAME)
---------------------
0
ops$tkyte%ORA11GR1> select sql_id, sql_text, is_bind_aware, is_bind_sensitive from v$sql where sql_text = 'select count(subobject_name) from t where id = :x';
SQL_ID SQL_TEXT I I
------------- ----------------------------------------------------------- - -
as2936sf1fnqu select count(subobject_name) from t where id = :x N Y
as2936sf1fnqu select count(subobject_name) from t where id = :x Y Y
as2936sf1fnqu select count(subobject_name) from t where id = :x Y Y
as2936sf1fnqu select count(subobject_name) from t where id = :x Y Y
there are three that are bind aware - the first one that is "not bind aware" is there ready to be aged out (no one will use it) - the three that are left
o one of them is for id=1
o one of them is for id=99
o the third one is for everything else - id=2,3,4, ......
adaptive cursor sharing will wait till it detects a problem, and then - it'll generate as few cursor images as it can.
Adaptive cursor sharing is a better cursor sharing similar (for so many reasons, not least of all - it works without having to set cursor_sharing away from exact!!!! any setting of cursor sharing other than exact shows immediately the developers didn't have a clue)