| Oracle Cursor Sharing Version 11.2.0.3 |
|---|
| General Information | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The following demos were inspired by Julian Dyke's
presentation at the UKOUG's November 2006 conference. What the doc says: Oracle automatically notices when applications send similar SQL statements to the database. The SQL area used to process the first occurrence of the statement is shared - that is, used for processing subsequent occurrences of that same statement. Therefore, only one shared SQL area exists for a unique statement. Because shared SQL areas are shared memory areas, any Oracle process can use a shared SQL area. The sharing of SQL areas reduces memory use on the database server, thereby increasing system throughput. In evaluating whether statements are similar or identical, Oracle considers SQL statements issued directly by users and applications as well as recursive SQL statements issued internally by a DDL statement. One of the first stages of parsing is to compare the text of the statement with existing statements in the shared pool to see if the statement can be shared. If the statement differs textually in any way, then Oracle does not share the statement. Exceptions to this are possible when the parameter CURSOR_SHARING has been set to SIMILAR or FORCE. When this parameter is used, Oracle first checks the shared pool to see if there is an identical statement in the shared pool. If an identical statement is not found, then Oracle searches for a similar statement in the shared pool. If the similar statement is there, then the parse checks continue to verify the executable form of the cursor can be used. If the statement is not there, then a hard parse is necessary to generate the executable form of the statement. Statements that are identical, except for the values of some literals, are called similar statements. Similar statements pass the textual check in the parse phase when the CURSOR_SHARING parameter is set to SIMILAR or FORCE. Textual similarity does not guarantee sharing. The new form of the SQL statement still needs to go through the remaining steps of the parse phase to ensure that the execution plan of the preexisting statement is equally applicable to the new statement. Setting CURSOR_SHARING to EXACT allows SQL statements to share the SQL area only when their texts match exactly. This is the default behavior. Using this setting, similar statements cannot shared; only textually exact statements can be shared. Setting CURSOR_SHARING to either SIMILAR or FORCE allows similar statements to share SQL. The difference between SIMILAR and FORCE is that SIMILAR forces similar statements to share the SQL area without deteriorating execution plans. Setting CURSOR_SHARING to FORCE forces similar statements to share the executable SQL area, potentially deteriorating execution plans. Hence, FORCE should be used as a last resort, when the risk of suboptimal plans is outweighed by the improvements in cursor sharing. The CURSOR_SHARING initialization parameter can solve some performance problems. It has the following values: FORCE, SIMILAR, and EXACT (default). Using this parameter provides benefit to existing applications that have many similar SQL statements. The optimal solution is to write sharable SQL, rather than rely on the CURSOR_SHARING parameter. This is because although CURSOR_SHARING does significantly reduce the amount of resources used by eliminating hard parses, it requires some extra work as a part of the soft parse to find a similar statement in the shared pool. Consider setting CURSOR_SHARING to SIMILAR or FORCE if both of the following questions are true:
Using CURSOR_SHARING = SIMILAR (or FORCE) can significantly improve cursor sharing on some applications that have many similar statements, resulting in reduced memory usage, faster parses, and reduced latch contention. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Data Dictionary Objects |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Modes |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Session Setting Syntax | ALTER SESSION SET <sharing_mode> = <mode_name>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ALTER SESSION SET cursor_sharing='EXACT'; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| System Setting Syntax | ALTER SYSTEM SET <sharing_mode> = <mode_name> [SCOPE=<BOTH|MEMORY|SPFILE]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ALTER SYSTEM SET cursor_sharing='EXACT' SCOPE=BOTH SID=*; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Demos | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Tom Kyte's Demo from asktom.oracle.com |
conn uwclass/uwclass CREATE TABLE t (x NUMBER, y NUMBER); alter system flush shared_pool; alter system flush shared_pool; select count(y) from t where x = 1; select count(y) from t where x = 10; select count(y) from t where x = 20; select count(y) from t where x = 30; select count(y) from t where x = 40; select count(y) from t where x = 50; select count(y) from t where x = 60; select count(y) from t where x = 70; select count(y) from t where x = 80; select count(y) from t where x = 99; set linesize 121 col sql_text format a50 col value_string format a5 SELECT s.sql_text, b.value_string, s.plan_hash_value FROM gv$sql_bind_capture b, gv$sql s WHERE s.hash_value = b.hash_value AND s.address = b.address AND s.child_number = b.child_number AND s.sql_text LIKE 'select count(y) from t where x =%'; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Query to determine parse statistics |
SELECT pa.SID, pa.VALUE "Hard Parses", ex.VALUE "Execute Count" FROM V$SESSTAT pa, V$SESSTAT ex WHERE pa.SID = ex.SID AND pa.STATISTIC#=( SELECT STATISTIC# FROM V$STATNAME WHERE NAME = 'parse count (hard)') AND ex.STATISTIC#=( SELECT STATISTIC# FROM V$STATNAME WHERE NAME = 'execute count') AND pa.VALUE > 0; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Parent Cursors | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Cursor Sharing Demo |
conn / as sysdba set linesize 121 col name format a30 col value format a30 col sql_text format a65 -- verify default value of EXACT SELECT name, value FROM gv$parameter WHERE name LIKE '%cursor%'; -- if not set cursor sharing to EXACT ALTER SYSTEM SET cursor_sharing='EXACT' SCOPE=BOTH; -- verify default value of EXACT SELECT name, value FROM gv$parameter WHERE name LIKE '%cursor%'; -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; desc gv$sql -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; -- set cursor sharing to FORCE ALTER SYSTEM SET cursor_sharing='FORCE' SCOPE=BOTH; -- verify FORCE was set SELECT name, value FROM gv$parameter WHERE name LIKE '%cursor%'; -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; -- set cursor sharing to SIMILAR ALTER SYSTEM SET cursor_sharing='SIMILAR' SCOPE=BOTH; -- verify SIMILAR was set SELECT name, value FROM gv$parameter WHERE name LIKE '%cursor%'; -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Child Cursors | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Mismatch demos |
conn / as sysdba set linesize 121 col name format a30 col value format a30 col sql_text format a65 -- set cursor sharing to SIMILAR ALTER SYSTEM SET cursor_sharing='SIMILAR' SCOPE=BOTH; -- verify SIMILAR was set SELECT name, value FROM gv$parameter WHERE name LIKE '%cursor%'; -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; -- as SYS look in the shared pool SELECT address, child_address, sql_text, sql_id FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; desc v$sqlarea SELECT fetches, executions, parse_calls, disk_reads FROM v$sqlarea WHERE sql_id = '7f2fuwa2xyzyk'; SELECT application_wait_time, user_io_wait_time, cpu_time FROM v$sqlarea WHERE sql_id = '7f2fuwa2xyzyk'; SELECT optimizer_mode, optimizer_cost, sorts FROM v$sqlarea WHERE sql_id = '7f2fuwa2xyzyk'; SELECT latitude FROM uwclass.servers WHERE srvr_id = 4; -- ====================================== SELECT name, value FROM gv$parameter WHERE name LIKE '%optimizer_mode%'; -- default is ALL_ROWS. Let's change it ALTER SESSION SET optimizer_mode = CHOOSE; -- verify the change SELECT name, value FROM gv$parameter WHERE name LIKE '%optimizer_mode%'; SELECT latitude FROM uwclass.servers WHERE srvr_id = 5; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; -- we now have two child cursors. Let's see why desc gv$sql_shared_cursor
SELECT child_number, child_address, optimizer_mode_mismatch FROM gv$sql_shared_cursor WHERE address = '34329344'; -- ====================================== OPTIMIZER PARAMETERS -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; SELECT name, value FROM gv$parameter WHERE name LIKE '%optimizer_index_caching%'; -- default is ALL_ROWS. Let's change it ALTER SESSION SET optimizer_index_caching = 40; -- verify the change SELECT name, value FROM gv$parameter WHERE name LIKE '%optimizer_index_caching%'; SELECT latitude FROM uwclass.servers WHERE srvr_id = 4; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; SELECT child_number, child_address, optimizer_mismatch FROM gv$sql_shared_cursor WHERE address = '34291F58'; -- ====================================== STATISTICS COLLECTION -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as the client run two similar SQL statements SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; SELECT latitude FROM uwclass.servers WHERE srvr_id = 2; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; exec dbms_monitor.session_trace_enable; SELECT latitude FROM uwclass.servers WHERE srvr_id = 3; exec dbms_monitor.session_trace_disable; SELECT latitude FROM uwclass.servers WHERE srvr_id = 4; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; SELECT child_number, child_address, stats_row_mismatch FROM gv$sql_shared_cursor WHERE address = '34291F58'; -- ====================================== TRANSLATION MISMATCH -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as client1 run SQL statement SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; -- as client2 run SQL statement SELECT latitude FROM uwclass.servers WHERE srvr_id = 1; -- as SYS look in the shared pool SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; -- as client1 run SQL statement SELECT latitude FROM servers WHERE srvr_id = 1; -- as SYS look in the shared pool / multiple children not created SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%uwclass%'; -- as client1 GRANT SELECT ON servers TO abc; -- as ABC CREATE TABLE servers AS SELECT * FROM uwclass.servers; -- as client1 run SQL statement SELECT latitude FROM servers WHERE srvr_id = 1; -- as client2 run SQL statement SELECT latitude FROM servers WHERE srvr_id = 1; -- as SYS look in the shared pool / multiple children not created SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%servers%'; SELECT child_number, child_address, translation_mismatch FROM gv$sql_shared_cursor WHERE address = '3013AF5C'; -- ====================================== BIND MISMATCH - finish down -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as client 1 VARIABLE b1 VARCHAR2(15); BEGIN SELECT netaddress INTO :b1 FROM servers WHERE srvr_id = 1; END; / print b1 VARIABLE b2 VARCHAR2(15); BEGIN SELECT netaddress INTO :b2 FROM servers WHERE srvr_id = 1; END; / SELECT latitude FROM servers WHERE netaddress = :b2; BEGIN SELECT netaddress INTO :b1 FROM servers WHERE srvr_id = 2; END; / SELECT latitude FROM servers WHERE netaddress = :b 1; SELECT child_number, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%latitude%'; -- clear all cached SQL statements ALTER SYSTEM FLUSH SHARED_POOL; ALTER SYSTEM FLUSH SHARED_POOL; -- as client 1 VARIABLE b1 VARCHAR2(15); BEGIN SELECT netaddress INTO :b1 FROM servers WHERE srvr_id = 1; END; / SELECT latitude FROM servers WHERE netaddress = :b1; VARIABLE b1 VARCHAR2(30); BEGIN SELECT netaddress INTO :b1 FROM servers WHERE srvr_id = 1; END; / SELECT latitude FROM servers WHERE netaddress = :b1; SELECT address, child_address, sql_text FROM gv$sql WHERE sql_fulltext LIKE '%latitude%'; SELECT child_number, child_address, bind_mismatch FROM gv$sql_shared_cursor WHERE address = '?'; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Related Topics |
| CURSOR_SHARING_EXACT |
| Tuning |
| This site is maintained by Dan Morgan. Last Updated: | This site is protected by copyright and trademark laws under U.S. and International law. © 1998-2013 Daniel A. Morgan All Rights Reserved | |||||||||
|
|
||||||||||