Skip to Main Content
  • Questions
  • Please, demistify session cached cursors

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Dayne.

Asked: July 06, 2010 - 2:14 am UTC

Last updated: July 06, 2010 - 8:08 am UTC

Version: 10.2.0.1

Viewed 1000+ times

You Asked

Hi Tom,

We are running MOD_PLSQL on our 10.2.0.1 db server and are constantly having performance problems. The AWR report shows latch waits as the highest wait taking as much as 35% of DB time. The ADDM report says that the database is soft parsing too much. It recommends increasing session cached cursors to reduce the number of soft parses.

In response to this, I have set the DAD to perform a session reinitialize which should keep the cached cursors open at the end of each call (problem persists). I have increased session cached cursors from 0 to 100 (problem persists). I am now looking at the program logic to try and determine why it is not using the session cached cursors.

In my quest to understand cached cursors better, I put together a small code comparison and came out with a result I just simply don't understand. Perhaps you could help.

In my example below, I have two procedures both opening cursors to all_objects. One procedure uses a string (with bind variables) to open the sql, and the other uses embeded SQL to open the identical cursor. I would have assumed the embeded SQL procedure to perform better than the string sql procedure (in terms of parsing and latching). The strange thing is though... it doesn't.

My test seems to tell me that the string SQL will make use of session cached cursors while the embeded SQL will not. Why is this happening? Why is the string SQL "reusable" and the embeded not?
dayneo@SANDBOX> create or replace procedure test_string_cursor as
  2           l_rc    sys_refcursor;
  3           l_sql   varchar2(32767);
  4           l_value number := 1;
  5  begin
  6           -- using "where 1=1" to differenciate query from hardcoded sql
  7           l_sql := 'select object_name from user_objects where 1=:bv';
  8           open l_rc for l_sql using l_value;
  9           close l_rc;
 10  end test_string_cursor;
 11  /

Procedure created.

dayneo@SANDBOX> SHOW ERRORS
No errors.
dayneo@SANDBOX> create or replace procedure test_hardcoded_cursor as
  2           l_rc    sys_refcursor;
  3           l_value number := 2;
  4  begin
  5           -- using "where 2=2" to differenciate query from string sql
  6           open l_rc for select object_name from user_objects where 2 = l_value;
  7           close l_rc;
  8  end test_hardcoded_cursor;
  9  /

Procedure created.

dayneo@SANDBOX> SHOW ERRORS
No errors.
dayneo@SANDBOX> alter session set session_cached_cursors=10;

Session altered.

dayneo@SANDBOX> begin
  2           -- warmup
  3           test_string_cursor();
  4           test_hardcoded_cursor();
  5           runstats_pkg.rs_start();
  6           for l_count in 1..10000 loop
  7               test_string_cursor();
  8           end loop;
  9           runstats_pkg.rs_middle();
 10           for l_count in 1..10000 loop
 11               test_hardcoded_cursor();
 12           end loop;
 13           runstats_pkg.rs_stop(500);
 14  end;
 15  /
Run1 ran in 200 hsecs
Run2 ran in 201 hsecs
Run1 ran in 99.5% of the time
    
Name                                Run1      Run2      Diff
STAT...session cursor cache hi    10,000         0   -10,000
LATCH.library cache               40,004    50,011    10,007
LATCH.library cache pin           40,004    20,010   -19,994
LATCH.library cache lock               0    40,002    40,002
    
Run1 latches total versus runs -- difference and pct
      Run1      Run2      Diff     Pct
    80,179   110,493    30,314  72.56%

PL/SQL procedure successfully completed.

I found the same behavior on the 10.1.0.4 db.

Thanks Tom


and Tom said...

ref cursors are never cached open, never - not in any case.

session cached cursors cannot ever decrease the parse count - never, it can only make the parse take less cpu cycles. It (session cached cursors) can turn a soft parse into a "softer soft parse", you would see it doing its work by seeing an increase in the statistic "session cursor cache hits"

I can confirm however that in 11g - both release 1 and release 2 - an enhancement was made to allow session cached cursors to impact both native dynamic SQL ref cursors (which you see happening in 10g) as well as static SQL (which you do not see happening in 10g).

So, in 11g - the static sql will employ session cached cursors as well as the native dynamic sql.


Is this answer out of date? If it is, please let us know via a Comment

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library