[Reproduced] Oracle cursor sharing, the concept of parent cursor and child cursor

One of the main purposes of Oracle's design of shared pool memory is statement sharing. Through statement sharing, statement parsing time is saved, thereby improving performance. If explaining shared pool memory is too much work, here is just a very simple demonstration.

To view statement sharing, you can use two data dictionaries: V$SQLAREA and V$SQL
V$SQLAREA: retain the parent cursor information of the SQL statement, which can be identified by SQL_ID, where the VERSION_COUNT column represents the number of child cursors
V$SQL: retains the SQL statement The child cursor information can be identified by SQL_ID and CHILD_NUMBER

V$SQL_SHARED_CURSOR: The reason for the statement to generate the child cursor


First confirm the parameter cursor_sharing, the default value is EXACT, that is to say, only when the bind variable is not used, the statement must be exactly the same. It can be shared, including capitalization, spaces, carriage returns, etc. All must be the same.
SQL> conn / as sysdba
Connected.
SQL> show parameter cursor_sharing
NAME TYPE VALUE
---------------------------------- -------------- ------------------------------
cursor_sharing string EXACT

clears the shared_pool memory, This command can be used in experiments, be careful in production system libraries

SQL> alter system flush shared_pool;
System altered.


Under the SCOTT user and the TJ user, there are exactly the same tables called demo. This is the experimental scenario I prepared. For the following operations, the light color represents the first window or session, and the dark color represents the first window or session. Another window or session query dynamic performance view information verification


In the first window:
SQL> conn scott/tiger
Connected.
SQL> select * from demo;

     EMPNO ENAME SAL
---------- ----- ----- ----------
      7369 SMITH 1200
      7499 ALLEN 1600
      7521 WARD 1250
      7566 JONES 2975

SQL> select empno,ename from demo where empno=7369;

     EMPNO ENAME
-------- -- ----------
      7369 SMITH

Since the above statement is executed for the first time after clearing the share pool, Oracle needs to perform hard parsing to generate cursors, which are exactly a parent cursor and a child cursor, which can be found through V$SQLAREA and V$SQL respectively. Information



in the second window:
[oracle@asm11g workshop]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.3.0 Production on Sun Sep 16 21:20:24 2012
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Automatic Storage Management, OLAP, Data Mining
and Real Application Testing options

SQL> get qs.sql
  1 col sql_text for a50
  2 set linesize 120
  3 col exec for 999
  4 col invalid for 99
  5 col loads for 999
  6 select sql_text,
  7         sql_id,
  8         hash_value,
  9         executions exec,
10         loads,
11         invalidations invalid
12  from v$sqlarea
13* where sql_text like '&text%'
SQL> @qs
Enter value for text: select empno
old   9: where sql_text like '&text%'
new   9: where sql_text like 'select empno%'

SQL_TEXT                                           SQL_ID         HASH_VALUE EXEC LOADS INVALID
-------------------------------------------------- -------------  ---------- ---- ----- -------
select empno,ename from demo where empno=7369      dhdkpzyv9b1w7  3063252871    1     1       0



SQL> select sql_id,child_number,executions,loads from v$sql where sql_id='dhdkpzyv9b1w7';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS
------------- ------------ ---------- -----
dhdkpzyv9b1w7 0 1 1

By querying, we can see that the V$SQLAREA data dictionary contains the information of the parent cursor, the statement is parsed (LOADS) once, and executed (EXEC ) once, of course, similar information can be seen in V$SQL.



Go to the first window:
SQL> select empno,ename from demo where empno=7369;

     EMPNO ENAME
---------- ----------
      7369 SMITH

execute the previous statement again, Since the statement already has a cursor in the share pool memory, the statement will be shared.



To the second window:
SQL> @qs
Enter value for text: select empno
old 9: where sql_text like '&text%'
new 9: where sql_text like 'select empno%'

SQL_TEXT SQL_ID HASH_VALUE EXEC LOADS INVALID
-------------------------------------------- ------ ------------- ---------- ---- ----- -------
select empno,ename from demo where empno=7369 dhdkpzyv9b1w7 3063252871 2 1 0



SQL> select sql_id,child_number,executions,loads from v$sql where sql_id='dhdkpzyv9b1w7';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS
------------- -- ---------- ---------- -----
dhdkpzyv9b1w7 0 2 1

Through the above query, we can see that the statement is parsed (LOADS) once and executed (EXEC) Twice, the same information can be seen in the child cursor.



To the first window:
SQL> select empno,ename from demo where empno=7499;

     EMPNO ENAME
---------- ----------
      The difference between the statement 7499 ALLEN

and the statement just now is that I changed the condition to 7499, so this is a brand new statement. Oracle has to do hard parsing and apply for a new parent-child cursor in memory.



Second window:

SQL> @qs
Enter value for text: select empno
old 9: where sql_text like '&text%'
new 9: where sql_text like 'select empno%'

SQL_TEXT SQL_ID HASH_VALUE EXEC LOADS INVALID
------- ------------------------------------------- ------- ------ ---------- ---- ----- -------
select empno,ename from demo where empno=7499 0m3wzw5mrdg8z 1735834911 1 1 0
select empno, ename from demo where empno=7369 dhdkpzyv9b1w7 3063252871 2 1 0



to the first window:
Switch the user to tj, the tj user also has the same table demo, execute select empno,ename from demo where empno=7369;
SQL> conn tj/tj
Connected.
SQL> select empno,ename from demo where empno=7369;

     EMPNO ENAME
- --------- ----------
      7369 SMITH



to the second window:
SQL> @qs
Enter value for text: select empno
old 9: where sql_text like '&text%'
new 9 : where sql_text like 'select empno%'

SQL_TEXT SQL_ID HASH_VALUE EXEC LOADS INVALID
----------------------------------- --------------- ------------- ---------- ---- ----- --- ----
select empno,ename from demo where empno=7499 0m3wzw5mrdg8z 1735834911 1 1 0
select empno,ename from demo where empno=7369 dhdkpzyv9b1w7 3063252871 3 2 0

SQL> select sql_id,child_number,executions,loads from v$sql where sql_id='dhdkpzyv9b1w7';

SQL_ID CHILD_NUMBER EXECUTIONS LOADS
---------- --- ------------ ---------- -----
dhdkpzyv9b1w7 0 2 1
dhdkpzyv9b1w7 1 1 1



Although the statement under the tj user and the one written under the scott user The statements are exactly the same, but the semantics are obviously different. The two demo tables belong to different users, so we see that Oracle's parent cursor parsing (LOADS) is incremented by 1, and the number of executions is also incremented by 1. From the perspective of the parent cursor, the statement is Shared, and in the child cursor, there is a difference, a new child cursor CHILD_NUMBER is 1, parsed (LOADS) once, and executed once.



To the first window:

execute the statement again
SQL> select empno,ename from demo where empno=7369;

     EMPNO ENAME
---------- ----------
      7369 SMITH



to the second window:
SQL> @qs
Enter value for text: select empno
old   9: where sql_text like '&text%'
new   9: where sql_text like 'select empno%'

SQL_TEXT                                           SQL_ID         HASH_VALUE EXEC LOADS INVALID
-------------------------------------------------- -------------  ---------- ---- ----- -------
select empno,ename from demo where empno=7499      0m3wzw5mrdg8z  1735834911    1     1       0
select empno,ename from demo where empno=7369      dhdkpzyv9b1w7  3063252871    4     2       0

SQL> select sql_id,child_number,executions,loads from v$sql where sql_id='dhdkpzyv9b1w7';

SQL_ID        CHILD_NUMBER EXECUTIONS LOADS
------------- ------------ ---------- -----
dhdkpzyv9b1w7 0 2 1
dhdkpzyv9b1w7 1 2 1

We see that the parent cursor parsing times of the statement do not increase, and the execution times increase by 1. For child cursors, the execution times of child cursors whose CHILD_NUMBER is 1 increase by 1.



There are many reasons for the generation of sub-cursors, such as my example of changing the user schema (SCHEMA) above. Of course, there are many other reasons that can lead to the generation of sub-cursors, such as changes in the optimizer mode, or peeping of bound variables, etc. If If you want to determine what is the cause, you need to look at v$sql_shared_cursor
For the example just now, it belongs to authentication/thing check mismatch

SQL> select sql_id,CHILD_NUMBER,AUTH_CHECK_MISMATCH from v$sql_shared_cursor where sql_id='dhdkpzyv9b1w7';

SQL_ID CHILD_NUMBER A
------------- ------------ -
dhdkpzyv9b1w7 0 N
dhdkpzyv9b1w7 1 Y

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326664718&siteId=291194637