By Franck Pachot
.
I usually don’t advice to set CURSOR_SHARING=FORCE but imagine your application requires it, you forgot it (or tried to do without) on migration and then everything is slow. You want to change it, but when does it take effect? New execution? New parsing? New session?
EXACT
I have the default value where parent cursor is shared only when sql_text is the same:
SQL> show parameter cursor_sharing
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cursor_sharing string EXACT
And I check with a query that the predicate is not changed:
SQL> select * from dual where dummy='X';
D
-
X
SQL> select * from table(dbms_xplan.display_cursor) where plan_table_output like '%filter%';
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("DUMMY"='X')
FORCE
I change at system (=instance) level
SQL> alter system set cursor_sharing=force;
System altered.
SQL> show parameter cursor_sharing
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cursor_sharing string FORCE
I tested without session cached cursors:
SQL> alter session set session_cached_cursors=0;
Session altered.
and even from another session
SQL> connect / as sysdba
Connected.
But the predicate still has its predicate:
SQL> select * from dual where dummy='X';
D
-
X
SQL> select * from table(dbms_xplan.display_cursor) where plan_table_output like '%filter%';
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("DUMMY"='X')
No invalidation, no new cursor. Same old statement.
FLUSH SHARED_POOL
Only when I flush the shared_pool I can execute the statement with literals replaced:
SQL> alter system flush shared_pool;
System altered.
SQL> select * from dual where dummy='X';
D
-
X
SQL> select * from table(dbms_xplan.display_cursor) where plan_table_output like '%filter%';
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("DUMMY"=:SYS_B_0)
If you fear a hard parse fest, you can flush specific cursors. I’ve documented the procedure in a previous post.
Update 27-JUN-2016
The previous sentence was wrong. Unfortunately, dbms_shared_pool.purge purges only the library cache object heaps and not the object handles. So this is not a solution to get cursor_sharing change immediate effect.
Autotrace
As a side note, do not rely on autotrace for that
SQL> set autotrace on explain
SQL> select * from dual where dummy='X';
D
-
X
Execution Plan
----------------------------------------------------------
Plan hash value: 272002086
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| DUAL | 1 | 2 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DUMMY"='X')
Just one more thing that is special with autotrace…
Conclusion
I don’t know exactly how cursor_sharing=force is managed. I thought that the literal replacement occurred before searching for parent cursor. Don’t hesitate to comment here if you know the ‘why’ behind this behavior. My goal here was just to test what has to be done in order to have immediate effect of cursor_sharing change.
alvussar
20.05.2023ALTER SYSTEM SET cursor_sharing='FORCE' SCOPE=BOTH SID='*';
ALTER SYSTEM SET cursor_sharing='FORCE' SCOPE=MEMORY SID='*';