- flush the shared_pool
- grant: i.e. grant select on t to system;
- comment: i.e. comment on table t is 'I am a table';
- dbms_stats.gather_table_stats (no_invalidate should not be true);
Of course if I add a new column to a table, I am sure I can invalidate the cursor too, but this is not a choice obviously in the middle of day, even I do want to add a column. This is not a harmless DDL.
Below is the test abount 'COMMENT':
(1) I first created a table with one row having value 1 and 1999 rows having value 99 for its only column id. I had a histogram on that columne collected. So if I have predicate id=1, index scan should be used and if I have id=99, full table scan is preferred.
denis@TESTDB920> create table t 2 as 3 select 4 case when rownum=1 5 then 1 6 else 99 7 end id, 8 a.* 9 from all_objects a 10 where rownum <=2000 11 / Table created. denis@TESTDB920> create index t_idx on t(id); Index created. denis@TESTDB920> begin 2 dbms_stats.gather_table_stats 3 (user, 4 'T', 5 method_opt=>'for all indexed columns size 254'); 6 end; 7 / PL/SQL procedure successfully completed.
(2) I then executed a SQL statement twice with different bind variable values, using value 1 first.
denis@TESTDB920> variable id number
denis@TESTDB920> exec :id := 1
PL/SQL procedure successfully completed.
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
97
denis@TESTDB920>
denis@TESTDB920> exec :id := 99
PL/SQL procedure successfully completed.
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
6361608
denis@TESTDB920> select hash_value, address, child_number, executions, plan_hash_value, invalidations from
2 v$sql where sql_text like 'select%denis%' and sql_text not like 'select hash_value%';
HASH_VALUE ADDRESS CHILD_NUMBER EXECUTIONS PLAN_HASH_VALUE INVALIDATIONS
---------- ---------------- ------------ ---------- --------------- -------------
1403451991 000000039F798070 0 2 3178687684 0
(3) Now I invalidated the cursor by executiong a COMMENT stateemnt, noticed from v$sql: invalidations=1
denis@TESTDB920> comment on table t is 'I am ok';
Comment created.
denis@TESTDB920>
denis@TESTDB920> select hash_value, address, child_number, executions, plan_hash_value, invalidations from
2 v$sql where sql_text like 'select%denis%' and sql_text not like 'select hash_value%';
HASH_VALUE ADDRESS CHILD_NUMBER EXECUTIONS PLAN_HASH_VALUE INVALIDATIONS
---------- ---------------- ------------ ---------- --------------- -------------
1403451991 000000039F798070 0 0 0 1
(4) Next I executed the same sql statement 4 times. Since the cursor was invalidated, Oracle would need to re-parse the sql. As I first used bind value 99 as compared to 1 in the step 2, as expected the cursor got exected with different plan, notice the plan hash value is different from that in the step 2
denis@TESTDB920>
denis@TESTDB920> exec :id := 99
PL/SQL procedure successfully completed.
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
6361608
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
6361608
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
6361608
denis@TESTDB920> select /* denis */ sum(object_id) from t where id= :id;
SUM(OBJECT_ID)
--------------
6361608
denis@TESTDB920> select hash_value, address, child_number, executions, plan_hash_value, invalidations from
2 v$sql where sql_text like 'select%denis%' and sql_text not like 'select hash_value%';
HASH_VALUE ADDRESS CHILD_NUMBER EXECUTIONS PLAN_HASH_VALUE INVALIDATIONS
---------- ---------------- ------------ ---------- --------------- -------------
1403451991 000000039F798070 0 4 1842905362 1
update 10/21/2013 -
we can use: sys.dbms_shared_pool.purge procedure to purge a particular cursor. For example:
SQL> select address, hash_value from v$sqlarea
2 where sql_text = 'select count(c2) from skew where c1 = :x';
ADDRESS HASH_VALUE
-------- ----------
27308318 2934790721
SQL> exec sys.dbms_shared_pool.purge('&address, &hash_value','c')
PL/SQL procedure successfully completed.
see : http://prutser.wordpress.com/2009/04/19/flushing-a-cursor-out-of-the-library-cache/
No comments:
Post a Comment