11.1.3 BindVariable Peeking
In bind variablepeeking (also known as bind peeking), the optimizer looks at thevalue in a bind variable when the database performs a hard parse of astatement.
When a query usesliterals, the optimizer can use the literal values to find the best plan. However, when aquery uses bind variables, the optimizer must select the best plan without thepresence of literals in the SQL text. This task can be extremely difficult. By peeking at bindvalues the optimizer can determine the selectivity of a WHERE clause condition as ifliterals had been used, thereby improving the plan.
Example 11-1 Bind Peeking
Assume that thefollowing 100,000 row emp table exists inthe database. The table has the following definition:
SQL> DESCRIBE emp
Name Null? Type
---------------------- -------- ----------------------------------
ENAME VARCHAR2(20)
EMPNO NUMBER
PHONE VARCHAR2(20)
DEPTNO NUMBER
The data issignificantly skewed in the deptno column. The value10 is found in 99.9% of the rows. Each of the other deptno values (0 through 9) is found in 1% of the rows. You have gathered statistics for the table,resulting in a histogram on the deptno column. You definea bind variable and query emp using the bindvalue 9 as follows:
VARIABLE deptno NUMBER
EXEC :deptno := 9
SELECT /*ACS_1*/ count(*), max(empno)
FROM emp
WHERE deptno = :deptno;
The query returns10 rows:
COUNT(*) MAX(EMPNO)
---------- ----------
10 99
To generate theexecution plan for the query, the database peeked at the value 9 during the hard parse. The optimizer generated selectivityestimates as if the user had executed the following query:
select /*ACS_1*/ count(*), max(empno)
from emp
where deptno = 9;
When choosing aplan, the optimizer only peeks at the bind value during the hard parse. This planmay not be optimal for all possible values.
11.1.3.1 Adaptive Cursor Sharing
The adaptive cursorsharing feature enables a single statement that contains bind variables touse multiple execution plans. Cursor sharing is"adaptive" because the cursor adapts its behavior so that thedatabase does not always use the same plan for each execution or bind variablevalue.
For appropriatequeries, the database monitors data accessed over time for different bindvalues, ensuring the optimal choice of cursor for a specific bind value. Forexample, the optimizer might choose one plan for bind value 9 and a different plan for bind value 10. Cursor sharing is"adaptive" because the cursor adapts its behavior so that the sameplan is not always used for each execution or bind variable value.
Adaptive cursorsharing is enabled for the database by default and cannot be disabled. Note that adaptive cursor sharing does not apply to SQLstatements containing more than 14 bind variables.
Note:
Adaptive cursorsharing is independent of the CURSOR_SHARING initializationparameter (see "Sharing Cursors forExisting Applications"). Adaptive cursor sharing isequally applicable to statements that contain user-defined and system-generatedbind variables.
11.1.3.1.1 Bind-Sensitive Cursors
A bind-sensitivecursor is a cursor whose optimal plan may depend on the value of a bindvariable. The database monitors the behavior of a bind-sensitive cursor thatuses different bind values to determine whether a different plan is beneficial.
The criteria usedby the optimizer to decide whether a cursor is bind-sensitive include thefollowing:
· The optimizer has peeked at the bindvalues to generate selectivity estimates.
· A histogram exists on the columncontaining the bind value.
Example 11-2 Bind-Sensitive Cursors
In Example 11-1 you queried the emp table using the bind value 9 for deptno. Now you run the DBMS_XPLAN.DISPLAY_CURSOR function to showthe query plan:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
The output is asfollows:
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time|
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 16 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 16 | 2 (0)| 00:00:01|
|* 3 | INDEX RANGE SCAN | EMP_I1 | 1 | | 1 (0)| 00:00:01|
----------------------------------------------------------------------------------
The plan indicatesthat the optimizer chose an index range scan, which is expected because of theselectivity (only 1%) of the value 9. You can query V$SQL to view statistics about the cursor:
COL BIND_SENSI FORMAT a10
COL BIND_AWARE FORMAT a10
COL BIND_SHARE FORMAT a10
SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS"BIND_SENSI",
IS_BIND_AWARE AS"BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE"
FROM V$SQL
WHERE SQL_TEXT LIKE 'select/*ACS_1%';
As shown in thefollowing output, one child cursor exists for this statement and has beenexecuted once. A small number of buffer gets are associated with the childcursor. Because the deptno data is skewed,the database created a histogram. This histogram led the database to mark thecursor as bind-sensitive (IS_BIND_SENSITIVE is Y).
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 1 56 Y N Y
For each executionof the query with a new bind value, the database records the executionstatistics for the new value and compares them to the execution statistics forthe previous value. If execution statistics vary greatly, then the databasemarks the cursor bind-aware.
11.1.3.1.2 Bind-Aware Cursors
A bind-awarecursor is a bind-sensitive cursor eligible to use different plans fordifferent bind values. After a cursor has been made bind-aware, the optimizerchooses plans for future executions based on the bind value and its selectivityestimate.
When a statement with abind-sensitive cursor executes, the database decides whether to mark the cursorbind-aware. The decision depends on whether the cursor produces significantlydifferent data access patterns for different bind values. If the database marksthe cursor bind-aware, then the next time that the cursor executes the databasedoes the following:
· Generates a new plan based on thenew bind value.
· Marks the original cursor generatedfor the statement as not shareable (V$SQL.IS_SHAREABLE is N). This cursor is no longer usable and will be among the first to be agedout of the shared SQL area.
Example 11-3 Bind-Aware Cursors
In Example 11-1 you queried empusing the bind value 9. Now you query emp using the bind value 10. The query returns99,900 rows that contain the value 10:
COUNT(*) MAX(EMPNO)
---------- ----------
99900 100000
Because the cursorfor this statement is bind-sensitive, the optimizer assumes that the cursor canbe shared. Consequently, the optimizer uses the same index range scan for thevalue 10 as for the value 9.
The V$SQL output shows that the same bind-sensitive cursor was executed a secondtime (the query using 10) and required manymore buffer gets than the first execution:
SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS"BIND_SENSI",
IS_BIND_AWARE AS"BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE"
FROM V$SQL
WHERE SQL_TEXT LIKE 'select/*ACS_1%';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 1010 Y N Y
Now you execute thequery using the value 10 a second time. Thedatabase compares statistics for previous executions and marks the cursor asbind-aware. In this case, the optimizer decides that a new plan is warranted,so it performs a hard parse of the statement and generates a new plan. The new planuses a full table scan instead of an index range scan:
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 208 (100)| |
| 1 | SORT AGGREGATE | | 1 | 16 | | |
|* 2 | TABLE ACCESS FULL| EMP | 95000 | 1484K| 208 (1)| 00:00:03 |
---------------------------------------------------------------------------
A query of V$SQL shows that the database created an additional child cursor (child number 1) that represents the plan containing the full table scan. This new cursorshows a lower number of buffer gets and is marked bind-aware:
SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS"BIND_SENSI",
IS_BIND_AWARE AS"BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE"
FROM V$SQL
WHERE SQL_TEXT LIKE 'select/*ACS_1%';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 1010 Y N Y
1 2 1522 Y Y Y
After you executethe query twice with value 10, you execute itagain using the more selective value 9. Because ofadaptive cursor sharing, the optimizer "adapts" the cursor andchooses an index range scan rather than a full table scan for this value.
A query of V$SQL indicates that the database created a new child cursor (child number 2) for the execution of the query:
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 1010 Y N N
1 1 1522 Y Y Y
2 1 7 Y Y Y
Because thedatabase is now using adaptive cursor sharing, the database no longer uses theoriginal cursor (child 0), which is notbind-aware. The shared SQL area will age out the defunct cursor.
11.1.3.1.3 Cursor Merging
If the optimizercreates a plan for a bind-aware cursor, and if this plan is the same as anexisting cursor, then the optimizer can perform cursor merging. In thiscase, the database merges cursors to save space in the shared SQL area. Thedatabase increases the selectivity range for the cursor to include theselectivity of the new bind.
Suppose you executea query with a bind value that does not fall within the selectivity ranges ofthe existing cursors. The database performs a hard parse and generates a newplan and new cursor. If this new plan is the same plan used by an existingcursor, then the database merges these two cursors and deletes one of the oldcursors.
11.1.3.2 ViewingBind-Related Performance Data
You can use the V$ views for adaptivecursor sharing to see selectivity ranges, cursor information (such as whether acursor is bind-aware or bind-sensitive), and execution statistics:
· V$SQL shows whether a cursor isbind-sensitive or bind-aware
· V$SQL_CS_HISTOGRAM shows thedistribution of the execution count across a three-bucket execution historyhistogram
· V$SQL_CS_SELECTIVITY shows theselectivity ranges stored for every predicate containing a bind variable if theselectivity was used to check cursor sharing
· V$SQL_CS_STATISTICS summarizes theinformation that the optimizer uses to determine whether to mark a cursorbind-aware.
Examples of Sharing Cursors with Peeked Bind Variables [ID 430208.1] |
To Bottom |
Modified:27-Mar-2013Type:HOWTOStatus:PUBLISHEDPriority:3 |
|
In this Document
Goal |
Fix |
|
Setup |
|
Example |
|
Conclusion |
References |
Oracle Database - Enterprise Edition - Version 9.2.0.1 and later
Information in this document applies to any platform.
Checked for relevance on 26-mar-2013
The purpose of this note is todemonstrate the concept of bind peeking. Bind peeking was introduced in Oracle9i and 10g. For more details about bind peeking, refer to:
Note387394.1 Query using Bind Variables is suddenlyslow.
Oracle® Database Performance Tuning Guide
11g Release 2 (11.2)
Part Number E16638-07
Chapter 11 The Query Optimizer
Section 11.1.3 Bind Variable Peeking
http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#PFGRF94588
The query optimizer peeks at the values of user-defined bind variables on thefirst invocation of a cursor. This feature allows the optimizer to determinethe selectivity of any WHERE clause condition. On subsequent invocations of thecursor, no peeking takes place, and the cursor is shared, based on the standardcursor-sharing criteria, even if subsequent invocations use different bindvalues.
The article provides an example of bindvariables in use.
Thefollowing section sets up a stand alone test environment including the creationof a user and a tablespace to hold the test table.
Please make sure you read this script thoroughly before applying it.
Connect /as sysdba
/
Drop tablespace BP_Tablespace Including Contents and Datafiles
/
Create Tablespace BP_Tablespace
Blocksize 8K
Datafile '/tmp/bp_tbs.dbf' Size 25M Reuse
Extent Management Local
Uniform Size 1M
Segment Space Management Manual
/
Drop User BP Cascade
/
Create User BP Identified By BP Default Tablespace BP_Tablespace QuotaUnlimited On BP_Tablespace
/
Grant DBA To BP
/
Connect BP/BP
/
-- My db_block_size is 8k
SQL> Show Parameter db_block_size
NAME TYPE VALUE
--------------- ----------- -----
db_block_size integer 819
-- Set Optimizer mode to choose
Alter Session Set Optimizer_Mode='ALL_ROWS'
/
-- Enabling bind peeking feature
Alter Session Set "_optim_peek_user_binds" = True
/
-- Testing with CPU costing off
Alter Session Set "_Optimizer_Cost_Model"='io'
/
-- Optimizer Features must be set to 9.2.x or higher
Alter Session Set Optimizer_Features_Enable = '10.2.0.3'
/
-- Set Cursor Sharing to Exact
Alter Session Set Cursor_Sharing=Exact;
Drop Table PreferredMeals
/
Create Table PreferredMeals
(EmpID Number(5),
Meal Varchar2(10)
)
/
Now that the table has been created, data is loaded that has a non-uniformdistribution (skewed data) to enable the generation two different executionplans based on predicate values.
In the following table, we have a survey that shows 74998 people prefer to eatmansaf while only one person likes Pasta and another person favours Kabab overmansaf and pasta ( its likely the survey results were collected in Jordan; notin Italy nor Turkey !)
Begin
For i in 1..74998 Loop
Insert Into PreferredMeals Values (i, 'Mansaf');
End Loop;
Insert Into PreferredMeals Values (74999, 'Kabab');
Insert Into PreferredMeals Values(75000, 'Pasta');
End;
.
/
Drop Index PrefMl_Indx
/
Create Index PrefMl_Indx
On
PreferredMeals(Meal)
/
Gather statistics and let Oracle decide which columns requires histograms andhow many buckets are required.
Exec DBMS_Stats.Gather_Table_Stats(OwnName => 'BP', TabName =>'PreferredMeals', Method_Opt => 'For All Indexed Columns Size Auto', Cascade=> True)
/
The example is based upon the followingselect:
Select Count(*)
From PreferredMeals
Where Meal = 'Mansaf'
/
Noteparticularly that Cursor_Sharing=Exact in the setup, which means that queriesthat differ only by their literal values will NOT be shared.
Examine the execution plan using"DBMS_XPlan.Display_Cursor"
Note:Do not use the Set AutoTrace EXP neither the Explan commands, as we need to seethe actual plan executed by accessing the memory directly.
This can be achieved either by using the new package DBMS_XPlan and/oraccessing V$SQLArea and V$SQL_Plan.
SQL> Select * From Table(DBMS_XPlan.Display_Cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
SQL_ID 7wcqj964zr3st, child number 0
-------------------------------------
Select Count(*) From PreferredMeals Where Meal = 'Mansaf'
Plan hash value: 831163055
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 54 (100)| |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX FAST FULL SCAN| PREFML_INDX | 74973 | 512K| 54 (2)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("MEAL"='Mansaf')
You will see either Index Fast FullScan or Table Full Access (this depends on many other factors thatare out of the realm of this note).
Now lets see the plan for a different value that we know only matches 1 row:
SQL> Select Count(*)
From PreferredMeals
Where Meal = 'Kabab'
/
Select * From Table(DBMS_XPlan.Display_Cursor);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
SQL_ID chd1rmnc76y9q, child number 0
-------------------------------------
Select Count(*) From PreferredMeals Where Meal = 'Kabab'
Plan hash value: 3082660612
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX RANGE SCAN| PREFML_INDX | 13 | 91 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("MEAL"='Kabab')
Notice that the SQL_ID is differentbecause Cursor_Sharing=Exact means the select is not shared.
We see Index Range Scan, since from the statistics, the optimizer knows thatthere is only one row satisfying the condition. So the optimizer chooses IndexRange access path which is cheaper.
Now if we define a bind variable and assign different values to it and examinethe execution plans:
SQL> Variable BP Varchar2(10)
Exec :BP := 'Mansaf'
/
PL/SQL procedure successfully completed.
SQL> Select Count(*)
From PreferredMeals
Where Meal = :BP
/
COUNT(*)
----------
74998
SQL> Select * From Table(DBMS_XPlan.Display_Cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
SQL_ID 4knqcd9t85h23, child number 0
-------------------------------------
Select Count(*) From PreferredMeals Where Meal = :BP
Plan hash value: 831163055
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 54 (100)| |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX FAST FULL SCAN| PREFML_INDX | 25000 | 170K| 54 (2)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("MEAL"=:BP)
With this new query we get a new planwhich has Index Fast Full Scan or FTS. If we now assign a different value forthe bind variable, in this case 'Pasta':
SQL> Exec :BP := 'Pasta'
PL/SQL procedure successfully completed.
SQL> Select Count(*)
From PreferredMeals
Where Meal = :BP
/
COUNT(*)
----------
1
SQL> Select * From Table(DBMS_XPlan.Display_Cursor);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
SQL_ID 4knqcd9t85h23, child number 0
-------------------------------------
Select Count(*) From PreferredMeals Where Meal = :BP
Plan hash value: 831163055
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 54 (100)| |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | INDEX FAST FULL SCAN| PREFML_INDX | 25000 | 170K| 54 (2)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("MEAL"=:BP)
Becasue the query is identical, it isshared and the first plan is re-used even though the value for the bindvariable has changed. In this case the same plan is not the optimal plan forthis value.
If you invalidate the cursor and try the test again, then the plan will beregenerated.
To invalidate any cursor, one of the following can be done:
1. Issue the command Alter System FlushShared_Pool;
2. Delete or change the cursor underlying objects statistics
3. Grant and/or revoke privileges on any of the cursor underlying objects
4. Alter cursor underlying objects
5. Bounce the instance
Alternatively we can either add dummy hint to the same query or change thequery
text(such as replace small letters with capitals) to enforce hard parsing it.
Select /*+ Hard parse me please */ Count(*)
From PreferredMeals
Where Meal = :BP
/
Examine the plan.
Select * From Table(DBMS_XPlan.Display_Cursor);
Oracle has peeked on the value of :BP and chosen the optimal plan once again.
When bind variables are used in astatement, it is assumed that cursor sharing is intended and that differentinvocations are supposed to use the same execution plan.
If different invocations of the cursor would significantly benefit fromdifferent execution plans, then bind variables may have been usedinappropriately in the SQL statement. Bind peeking works for a specific set ofclients, not all clients.
Note:
You can get all plans generated by the optimizer for the same SQL statement(i.e. with same SQL_ID) by using the function Display_Cursor in DBMS_Xplanpackage as follows:
SQL> select * from table(dbms_xplan.display_cursor('<sqlid>',null,'ADVANCED');
Unsafe Literals or Peeked Bind Variables [ID 377847.1] |
To Bottom |
Modified:13-Mar-2012Type:BULLETINStatus:PUBLISHEDPriority:3 |
|
In this Document
Purpose
Scope and Application
Unsafe Literals or Peeked Bind Variables
References
Oracle Server -Enterprise Edition - Version: 9.2.0.1 to 11.2.0.2 - Release: 9.2 to 11.2
Information in this document applies to any platform.
ALL PRODUCT ACCESS
This documentexplains regarding safe and unsafe literals and binds and their effect on queryoptimization.
This document isintended for Support Analysts and customers
Introduction
When bind variables are peeked, the parse engine makes a decision as to the'safety' of these peeked values for creating plans based upon whether it isfelt that different values could produce different plans.
The usual (but not the only) reason for such different plans is the use ofCURSOR_SHARING=SIMILAR and the presence of histogram column statistics on thecolumn that the bind is being compared with when using the Cost Based Optimizer(CBO). If there are histograms on the column, then the bind value may be deemedto be 'unsafe' because there is the potential chance that the different valuescould produce a different explain plan and the selection of a single plan forall values may not be 'safe' in terms of performance. If the bind is deemed'unsafe' then multiple children are created for each set of different boundvalues so that different plans can be associated with them. This occurs in afew scenarios but the most common is with histogram stats on an equalitypredicate.
CURSOR_SHARING=SIMILAR
With CURSOR_SHARING=SIMILAR whenever the optimizer examines anysystem-generated bind variable (ie where a literal has been replaced with abind) to make a decision, then that bind is checked to see if it shouldbe considered unsafe. The check made is :
Is the operatorNEITHER of '=' or '!='
OR
Are there Column Histograms present on the column.
If either of these is true then the bind is deemed to be unsafe and anew cursor will be created (So binds used in non equality predicates (eg >,<, >=, <=, LIKE) are unsafe). To check for whether a bind isconsidered unsafe see:
Note:261020.1 High Version Count with CURSOR_SHARING =SIMILAR or FORCE
With histogram stats on an equality predicate, this can cause severe problems(in terms of sharing) if there is, for example, a histogram on a main keycolumn.eg:
select ... from orders where orderid='literal';
If there is ahistogram on "orderid" then the bind will likely get marked unsafeand a new child will be produced for every single value of 'literal'. The SQLwould only be shared if the value of 'literal' matches exactly to a value usedalready.
Remember that if literals are converted to binds due to CURSOR_SHARING thenthey are subject to this checking, though unsafe binds are really only an issueif CURSOR_SHARING is SIMILAR.
In an OLTP type environment it would be sensible to only use histogramstatistics on columns that need it (i.e. where there are only a few distinctvalues with heavy skew and where different plans are needed for different predicatevalues). This way most SQL is shared and the absence of histograms keepspredicates safe except where needed.
CURSOR_SHARING = FORCE
If CURSOR_SHARING = FORCE binds can still be "unsafe" (in terms ofperformance) if used by the optimizer in decisions but this should not thenaffect share-ability of the SQL since CURSOR_SHARING=FORCE does not care aboutunsafe literals, but the cursor should still be shared. e.g.: In the aboveexample with orderid='literal', without histograms, the CBO does not need tolook at 'literal' to determine the selectivity of the predicate and so the binddoes not get marked unsafe.
If there are histograms, the predicate is marked as unsafe, but since FORCEuses the same plan whatever the circumstance, this does not matter. Only wherenon data literals for which different values alter the actual meaning of theSQL (e.g. order by 1 versus order by 2)will an unsafe predicate have an affect on plans.
Note that, prior to 11g, unsafe literals are NOT covered by 'bind mismatch' inV$SQL_SHARED_CURSOR as this is for user bind metadata mismatches. ie:different max bind lengths or bind type mismatches.
In 11g R2 (and 11.1.0.7 Patchset) a new column has been added toV$SQL_SHARED_CURSOR to check if literal replacement is used withCURSOR_SHARING=SIMILAR. The new column HASH_MATCH_FAILED is set to"Y" if sharing fails due to a hash mismatch, such as the case withmismatched histogram data or a range predicate marked as unsafe by literalreplacement. The unshared child cursors may have histogram data
on key columns used in equality predicates, or range predicates with literalswhich the optimizer has marked
as unsafe.
From the optimizer point of view, these additional plans for 'unsafe' bindvariables explain why multiple good plans may occur for peeked bind variables,even though the standard behavior for binds is to use peeked binds for theinitial parse and then use the resultant plan for all other iterations. Withunsafe binds, different plans for different peeked values can occur.
Background Information
This issue has been coming more in to focus with dynamic sampling in 10.2 sincethe default was changed from 1 to 2. When optimizer_dynamic_sampling is greaterthan 1 then Dynamic sampling emulates statistics + histograms. If histogramsare created, then binds may be marked as unsafe and produce different plans fordifferent values. With optimizer_dynamic_sampling > 1 a predicate can createa new version of a sql statement for each different value, even if there are nohistograms (or even statistics) on a table (since dynamic sampling may createthese in the background).
BUG:2992537 - 9I CBO USES MERGE JOIN CARTESIAN INAPPROPRIATELY.
BUG:3132098 - BIND PEEKING DOES NOT WORK FOR DUPLICATE BINDS .
BUG:5929112 - CURSOR_SHARING = SIMILAR|FORCE DO NOT SHARE SQL - DOCUMENTATION
NOTE:270056.1 - Parameter "OPTIMIZER_DYNAMIC_SAMPLING" behaviour haschanged since Oracle 9.2.0.3.
NOTE:296377.1 - Troubleshooting: High Version Count Issues
NOTE:336267.1 - Optimizer Dynamic Sampling (OPTIMIZER_DYNAMIC_SAMPLING)
NOTE:70075.1 - Use of bind variables in queries (Pre 9i)
NOTE:94036.1 - Init.ora Parameter "CURSOR_SHARING" Reference Note
Query using Bind Variables is suddenly slow [ID 387394.1] |
To Bottom |
Modified:09-May-2013Type:PROBLEMStatus:PUBLISHEDPriority:3 |
|
In this Document
Symptoms |
Changes |
Cause |
Solution |
References |
Oracle Database - Enterprise Edition -Version 9.0.1.0 to 10.2.0.4 [Release 9.0.1 to 10.2]
Information in this document applies to any platform.
Checked for relevance on 09-May-2013
The cursor has been re-parsed for some reason and a new planhas been generated.
There are many reasons why this might occur, not least the following:
NOTE the cursor will NOT get moved out by flushing the Shared Poolif it is pinned (ie in use)
One reason for this behavior may be explained by the use of afeature introduced in 9.x called bind peeking.
With this feature, the query optimizer peeks at the values of user-defined bindvariables on the first invocation of a cursor. This feature lets the optimizerdetermine the selectivity of any WHERE clause condition, based on this valuejust as if a literal had been used instead of a bind variable. On subsequentinvocations of the cursor, no peeking takes place, and the cursor is shared,based on the standard cursor-sharing criteria, even if subsequent invocationsuse different bind values.
In other words, the cursor is parsed once and the plan generatedis used many times.
This is find most of the time, BUT if the first set of bind valuesthat happen to be used when the cursor is first hard-parsed are notrepresentative of the majority of the data, then the plan may be inappropriatefor subsequent executions.
The Oracle 10.2 Database Performance Tuning Guide manual Chapter 13 "TheQuery Optimizer" says the following about peeking bind variables :-
"When bind variables are used in a statement, it is assumed that cursorsharing is intended and that different invocations are supposed to use the sameexecution plan. If different invocations of the cursor would significantlybenefit from different execution plans, then bind variables may have been used inappropriatelyin the SQL statement."
Bind peeking has been known to cause a different execution plan to be used ondifferent nodes of a RAC cluster because each node has its own SharedPool. Despite the same SQL, data, and statistics, the first time a cursorwas hard parsed on each node a different set of bind values was presented tothe optimizer, choosing a different plan on each node.
There is a hidden parameter ( "_optim_peek_user_binds") whichcontrols this feature's behavior, whose default value is TRUE.
Although a stable plan can be achieved by setting the parameter off, it must berealized that this stable plan is not necessarily the optimum plan for all bindvalues. Consider the following simple example where table has 10,000 rows andcol1 has an index.
SELECT<whatever>
FROM tablex
WHERE col1 BETWEEN :bind1 AND :bind2;
If this SQL is used, for example, with values 123 and 124 in orderto pick out 2 rows from the 10,000 rows in the table, then using an index wouldbe the obvious choice. However, if the same SQL is used with bind values123 and 9999, then we would be getting the vast majority of the rows and a fulltable scan would be more appropriate. But the optimizer cannot now know this,and does not change the plan accordingly.
In this sort of situation, it would perhaps be a good idea tomodify the application and have two separate modules/sections each with theabove SQL, but with a variation (perhaps modified with a hint) that will resultin the desired plan. The appropriate module could then be invokedprogrammatically. An example might be a situation where you use essentially thesame SQL to query the pay for one employee or all 10,000 employees. The queryfor one employee should use indexes, and the query for all employees should doa full table scan.
It is desirable to share cursors, particularly in an OLTP environment, for allthe good reasons outlined in :
Document 62143.1 Troubleshooting:Tuning the Shared Pool and Tuning Library Cache Latch Contention
Thus coding bind variables or perhaps using CURSOR_SHARING valuesof SIMILAR or FORCE is an appropriate path to follow, but it must be realizedthat having bind peeking may result in unpredictable execution plans dependenton the first set of bind values presented to the optimizer on hard parse. Tuning SQL with hints and coding your application to allow the use of theappropriate "version" of the SQL or using literal values is the preferredmethod of dealing with SQL having changing execution plans due to bind peeking,but if necessary this feature can also be disabled.
To set this feature off for the whole database set _OPTIM_PEEK_USER_BINDS=FALSEin the spfile/init.ora or just for the session :
alter sessionset "_OPTIM_PEEK_USER_BINDS"=FALSE;
For a good case study where this was a factor, please seefollowing note:
Document 369427.1 "CaseStudy: The Mysterious Performance Drop"
Document 5364143.8 Abstract:UNPREDICTABLE CHANGE IN QUERY OPTIMIZER PLAN (Fixed in 10.2.0.4 and 11.x)
Details:
It is possible for queries' execution plans to change without any modificationin statistics or optimizer environment. Usually, its interpreted like the planschanged "out of the blue". The reason for the change is that thecursor was taken out of the library cache for whatever reason (flush, MemoryPressure, DDLs,etc) and upon reload sometimes bind peeking is skipped for thecursor.
Note: Disabling Bind Peeking DOES NOT workaround the issue.
SUMMARY
=======
In summary, the bind peeking feature can give the optimizer better informationand allow a more appropriate execution plan if the bind values presented onhard parsing the cursor are representative. However, if there is a possibilitythey are NOT representative, then a plan which is sub-optimal for subsequentinvocations may result. Under these circumstances, one of the above strategiesshould be considered. Ultimately, in order to make the most appropriatedecision, a good knowledge of both the application and the data is required.
FOOTNOTE
========
Once a good plan is in operation for a key SQL statement, it always goodpractice to do the following:
a) for a 9.2 database capture, the statistics for the objects involved usingDBMS_STATS.EXPORT_TABLE_STATS. See:
Document 117203.1 "How toUse DBMS_STATS to Move Statistics to a Different Database" for moreinformation on how to do this).
These statistics could then be imported in an"emergency" to restore use of a good plan while a rogue plan isinvestigated. (NB take a copy of the "bad" stats before importing, ofcourse).
In 10g, whenever optimizer statistics are modified using the DBMS_STATSpackage, old versions of the statistics are saved automatically for futurerestoration, so the above is not necessary. See:
Document 452011.1"Restoring table statistics in 10G onwards".
b) capture the good execution plan so it can be used as a baseline reference inthe event that an
undesired change occurs.
For 9.2 See:
Document 260942.1:"Display Execution plans from Statements in V$SQL_PLAN".
In 10g, the view DBA_HIST_SQL_PLAN has historical information withrespect to execution plans. Use the following sql:
select * fromtable(dbms_xplan.display_awr('&sql_id'))
...as documented in following:
Document 362887.1 "A 10gEquivalant Process To The 9i Statspack Level 6 Execution Plan Output"
NOTE:117203.1 - How to UseDBMS_STATS to Move Statistics to a Different Database
NOTE:260942.1 - DisplayExecution plans from Statement's in V$SQL_PLAN
NOTE:338113.1 - Plans canchange despite no stats being regathered
NOTE:362887.1 - A 10gEquivalant Process To The 9i Statspack Level 6 Execution Plan Output
NOTE:369427.1 - Case Study:The Mysterious Performance Drop
NOTE:452011.1 - * RestoringTable Statistics (Oracle 10G Onwards)
NOTE:5364143.8 - Bug 5364143- Bind Peeking is not done upon query reload, Execution Plan changes
NOTE:62143.1 -Troubleshooting: Tuning the Shared Pool and Tuning Library Cache LatchContention
|
|
High Version Count with CURSOR_SHARING = SIMILAR or FORCE [ID 261020.1] |
To Bottom |
Modified:13-May-2013Type:PROBLEMStatus:PUBLISHEDPriority:3 |
|
Oracle Database - Enterprise Edition - Version 9.0.1.0 and later
Oracle Database - Personal Edition - Version 9.0.1.0 and later
Oracle Database - Standard Edition - Version 9.0.1.0 and later
Information in this document applies to any platform.
High version counts can easily cause high contention for library cache latches.A process parsing a SQL statement with many versions (children cursors) willneed to scan
through all these children while holding on to a library cache latch. This means that other processes needing the same latch will have to wait andcan lead to significant database-wide performance degradation.
CURSOR_SHARINGhas been changed to SIMILAR or FORCE.
EXAMPLE:
SELECTsql_text,version_count,address
FROM V$SQLAREA
WHERE sql_text like 'select /* TEST */%';
SQL_TEXT
---------------------------------------------------------------------------
VERSION_COUNT ADDRESS
------------- --------
select /* TEST */ * from emp where sal > :"SYS_B_0"
5 80EE4BF0
SELECT * FROM V$SQL_SHARED_CURSOR WHERE kglhdpar = '80EE4BF0';
ADDRESS KGLHDPAR U S O O S L S E B P I S T A B D L T R I I R L I O S M U T
-------- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
80FBD50C 80EE4BF0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
80EE816C 80EE4BF0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
....
....
Note:the above syntax using "kglhdpar" is for 9i, on 10g the query shoulduse "address" e.g.
SELECT * FROMV$SQL_SHARED_CURSOR WHERE address = '0000000386BC2E58';
See:
Document 296377.1 Troubleshooting: High Version Count Issues
If CURSOR_SHARING=SIMILAR, this could be expected behavior.
The difference between SIMILAR and FORCE is that SIMILAR forces similarstatements to share the SQL area without deteriorating execution plans.
SIMILAR causes statements that may differ in some literals, but are otherwiseidentical, to share a cursor, unless the literals affect either the meaning ofthe statement or the degree to which the plan is optimized. In this case theliteral is marked "unsafe" to be shared and the cursor will not beshared.
In the above example, the literal which is being replaced in the predicate:
sal >:"SYS_B_0"
isunsafe because the execution plan depends on its value.
In order to confirm if the issue is due to be "unsafe" get a 10046level 4 trace event from sessions executing that statement.For details of 10046trace see:
Document 21154.1 EVENT: 10046"enable SQL statement tracing (including binds/waits)"
Inthe trace look for the BIND information of the statement. If the field namedoacflg2 or flg2 has a value 300 this means the literal was replaced (100) andthe literal is unsafe (200).
If the child cursors keep increasing, it is likely that they will continue tobe created so the best suggestion is to check V$SQL.PLAN_HASH_VALUE of the
cursor with literal replaced.
select hash_value,plan_hash_value,count(*)from v$sql
where sql_text like '%:"SYS_B_0"%'
group by hash_value,plan_hash_value;
Ifsame hash_values have many different plan_hash_values, then the options arefollowing:
Ifsame hash_values only one plan_hash_value, then it is safer to setCURSOR_SHARING=FORCE instead as they all have the same execution plan.
If CURSOR_SHARING=FORCE then it could be a case of Bug:3406977 or similar bugs.
Bug:3406977 is about transitive predicate generation occurring in the query.
For example:
the query has predicates with the same literal value , e.g.
Col1 =16064 and Col2 = 16064
andthere is a predicate involving Col1 and Col2, e.g.
Col1 = Col2
In cases like this, obtain information from the cursorsusing following notes:
Document:438755.1 Formated V$SQL_SHARED_CURSOR Report by SQLID or Hash Value
Document:296377.1 Handling and resolving unshared cursors/large version_counts
and open a service request.
NOTE:296377.1 - Troubleshooting: High Version Count Issues
BUG:3151113 - ORA-4031 UNABLE TO ALLOCATE 4200 BYTES ("SHAREDPOOL",... "LIBRARY CACHE")
BUG:3406977 - HIGH VERSION COUNT DUE TO BINDS MARKED AS NON-DATA WITHCURSOR_SHARING=FORCE
BUG:3321724 - EXSESSIVE HIGH VERSION COUNT WHEN CURSOR_SHARING=SIMILAR
NOTE:3406977.8 - Bug 3406977 - High version count in V$SQL due to binds marked asnon-data with CURSOR_SHARING=FORCE
Optimizer Dynamic Sampling (OPTIMIZER_DYNAMIC_SAMPLING) [ID 336267.1] |
To Bottom |
Modified:13-May-2013Type:BULLETINStatus:PUBLISHEDPriority:3 |
|
Inthis Document
Purpose |
Scope |
Details |
Oracle Server -Enterprise Edition - Version 9.2.0.1 to 11.2.0.3 [Release 9.2 to 11.2]
Information in this document applies to any platform.
Checked for relevance on 17th April 2012
Thisarticle is provides some information regarding the parameter"optimizer_dynamic_sampling"
Partiesinterested in dynamic sampling details
DynamicSampling is a method of gathering additional statistics during optimization byrecursively sampling statements. When dynamic sampling is enabled, queries arerecursively generated by Oracle to test various selectivities based upon realvalues in order to improve their accuracy. This can result in the production ofbetter explain plans. It can be especially useful where there are correlatedpredicates in the query, where statistics are missing resulting in the use of guessesand also in cases where intermediate results are generated in temporary tablesfor which the optimizer would also have to use guesses otherwise.
Thereare overheads associated with dynamic sampling, and for fast executing queries,which already use a good access path, it is unlikely that further gains will bemade. In cases where the sampling makes up a small proportion of the total time(for all executions) then the overall benefits can outweigh the time taken togenerate and execute the recursive queries that gather the dynamic statistics.
Theparameter OPTIMIZER_DYNAMIC_SAMPLING controls the level of dynamic samplingperformed by the optimizer.
Thedefault level is 2 with levels up to 4 being most commonly used, higher levelssimply sampling more data. In simplified form, the Levels have the followingeffects:
Sofor example, you can set the following to Disable Dynamic Sampling and thenenable it at Level 4 respectively
alter session setOPTIMIZER_DYNAMIC_SAMPLING = 0;
alter session set OPTIMIZER_DYNAMIC_SAMPLING = 4;
Please refer to the following Manual for more details on the various levelsettings:
Oracle® DatabasePerformance Tuning Guide
11g Release2 (11.2)
Part Number E16638-06
Chapter 13 Managing Optimizer Statistics
Section 13.6.2.1 Dynamic Sampling Levels
http://docs.oracle.com/cd/E11882_01/server.112/e16638/stats.htm#PFGRF94760
High SQL Version Counts - Script to determine reason(s) [ID 438755.1] |
To Bottom |
Modified:10-Jun-2013Type:SCRIPTStatus:PUBLISHEDPriority:3 |
|
Inthis Document
Purpose |
|
Ask Questions, Get Help, And Share Your Experiences With This Article |
Requirements |
Configuring |
Instructions |
|
Generate reports for all cursors with more than 100 versions using SQL_ID (10g and up) |
|
Generate reports for all cursors with more than 100 versions using HASH_VALUE |
|
Generate the report for cursor with sql_id cyzznbykb509s |
Script |
Sample Output |
|
Discuss High Version Count Issues |
References |
Oracle Database -Personal Edition - Version 9.2.0.1 and later
Oracle Database - Enterprise Edition - Version 9.2.0.1 and later
Oracle Database - Standard Edition - Version 9.2.0.1 and later
Information in this document applies to any platform.
The view and function must be installed in SYS schema and run by SYS. (/ assysdba)
Works on 9iR2 , 10gR1, 10gR2, 11gR1, 11gR2
Thefunction generates a summary report from the v$sql_shared_cursor view and addsadditional diagnostic information depending on the reason code. It counts allthe versions that have 'Y' in any of the columns and if any have all 'N' too.This script is especially useful in determining the reason for high versioncounts and also may be useful to diagnose ORA-600 [17059] errors such as thatoutlined in :
Document 8922013.8 Bug 8922013 - OERI [17059] / excess child cursors for SQLreferencing REMOTE objects
Forinterpretation of the reasons for the versions presented in this report, see:
Document 296377.1 Troubleshooting: High Version Count Issues
Document 1377446.1 Troubleshooting Performance Issues
This procedure does not replace any output of v$sql_shared_cursor requested bysupport.
Would you like to explorethis topic further with other Oracle Customers, Oracle Employees, and IndustryExperts?
Clickhere to join thediscussion where you can ask questions, get help from others, and share yourexperiences with this specific article.
Discover discussions about other articles and helpful subjects by clicking here to access the main My Oracle Support Community page for Database Tuning.
Additionally If you have any feedback on this procedure then youcan add a comment to this article. Alternatively, you could forward it to theauthor: Abel Macias or makean entry on the blog :https://blogs.oracle.com/PerformanceDiagnosis/entry/diagnosis_of_a_high_version
Theview and function must be installed while connected to SYS (can be done with /as sysdba).
The function also must be run using a query as SYS.
The function accepts the Hash_Value or SQL ID (From 10gR1 and up) as input.
Download the script in the attachment: Scriptto create version_rpt function V3.2.1
and execute as follows:
connect / as sysdba
start version_rpt3_21.sql
SELECT b.*
FROM v$sqlarea a ,
TABLE(version_rpt(a.sql_id)) b
WHERE loaded_versions >=100;
SELECT b.*
FROM v$sqlarea a ,
TABLE(version_rpt(NULL,a.hash_value)) b
WHERE loaded_versions>=100;
SELECT * FROM TABLE(version_rpt('cyzznbykb509s'));
This sample code is provided for educational purposes only, and isnot supported by Oracle Support. It has been tested internally, however, we donot guarantee that it will work for you. Ensure that you run it in your testenvironment before using.
Seethe attachment section below.
Version Count Report Version 3.2.1 -- Today's Date 02-may-12 11:50
RDBMS Version :11.2.0.3.0 Host: XXXXXXXXXXXXXXXXXXXX Instance 1 : XXXXXXXXXX
==================================================================
Addr: 00000003D8B6A570 Hash_Value: 3993603298 SQL_ID 8swypbbr0m372
Sharable_Mem: 208913 bytes Parses: 477
Stmt:
0 select order#,columns,types from access$ where d_obj#=:1
1
Versions Summary
----------------
OPTIMIZER_MISMATCH :10
BIND_MISMATCH :1
LANGUAGE_MISMATCH :1
OPTIMIZER_MODE_MISMATCH :3
PX_MISMATCH :2
Total Versions:10
~
Plan Hash Value Summary
-----------------------
Plan Hash Value Count
=============== =====
872636971 11
0 1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Details for OPTIMIZER_MISMATCH :
1 versions with is_recur_flags = 167
2 versions with is_recur_flags = 161
9 versions with _pga_max_size = 614400 KB
7 versions with optimizer_mode = choose
3 versions with is_recur_flags = 35
7 versions with hash_area_size = 10485760
1 versions with optimizer_mode = rule
2 versions with advanced_queuing_internal_cursor = 1
2 versions with is_recur_flags = 163
1 versions with parallel_execution_enabled = false
1 versions with _pga_max_size = 204800 KB
10 versions with _optimizer_order_by_elimination_enabled = false
2 versions with is_recur_flags = 39
1 versions with hash_area_size = 2000000
1 versions with sort_area_size = 1000000
8 versions with _db_file_optimizer_read_count = 128
10 versions with _optimizer_cost_based_transformation = on
1 versions with parallel_threads_per_cpu = 4
1 versions with parallel_max_degree = 16
1 versions with _parallel_syspls_obey_force = false
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Details for BIND_MISMATCH :
Consolidated details for :
BIND_MISMATCH,USER_BIND_PEEK_MISMATCH,BIND_UACS_DIFF and
BIND_EQUIV_FAILURE (Mislabled as ROW_LEVEL_SEC_MISMATCH BY bug 6964441 in 11gR1)
from v$sql_bind_capture
COUNT(*) POSITION MIN(MAX_LENGTH) MAX(MAX_LENGTH) DATATYPE (PRECISION,SCALE)
======== ======== =============== =============== ======== ================
11 1 22 22 2 (,)
SUM(DECODE(column,Y, 1, 0) FROM V$SQL
IS_OBSOLETE IS_BIND_SENSITIVE IS_BIND_AWARE IS_SHAREABLE
=========== ================= ============= ============
0 0 0 9
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Details for LANGUAGE_MISMATCH :
No details available
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Details for OPTIMIZER_MODE_MISMATCH :
1 versions with RULE
9 versions with CHOOSE
2 versions with ALL_ROWS
~~~~~~~~~~~~~~~~~~~~~~~~~
Details for PX_MISMATCH :
No details available
####
To further debug Ask Oracle Support for the appropiate level LLL.
alter session set events 'immediate trace name cursortrace address 3993603298, level LLL';
To turn it off do use address 1, level 2147483648
================================================================
84 rows selected.
NOTE: If a large portionof the versions is reported as " Versions with ALL Columns as"N" " then this could be a bug in the reporting infrastructurelike Bug 12539487
FAQ: Adaptive Cursor Sharing (ACS) Frequently Asked Questions [ID 1518681.1] |
To Bottom |
Modified:15-Jan-2013Type:FAQStatus:PUBLISHEDPriority:3 |
|
Inthis Document
Purpose |
|
Ask Questions, Get Help, And Share Your Experiences With This Article |
Questions and Answers |
|
General ACS Questions |
|
Where are the main documents and Blogs relating to ACS? |
|
Are the ACS buckets based on actual row processes OR estimated row process ? |
|
Should STATISTIC_LEVEL be ALL with ACS? |
|
What is the impact of ACS on the Shared pool? |
|
Is there any impact/or consideration when using ACS with RAC database ? |
|
In RAC, when one instance gets bounced, will it get back the ACS cache from any other instance? |
|
Does ACS work for the SQL from PL/SQL? |
|
What is the suggestion to have the CURSOR_SHARING parameter for ACS to be effective? |
|
Is there a plan to have persistent ACS cursors? |
|
Licenses and Editions |
|
Is ACS a separately licensed feature? |
|
Does ACS work with Standard Edition ? |
|
ACS and Parameters |
|
How does CURSOR_SHARING=FORCE/EXACT affect ACS? |
|
When cursor_sharing=EXACT, will ACS still work? |
|
Are there drawbacks or negative effects to using the cursor_sharing=FORCE initialisation parameter for Oracle 11g database? Does this have effects on ACS? |
|
If an application uses literals and CURSOR_SHARING = EXACT, will adding a "bind aware" hint help? |
|
Are there any recommendations with regard to the SESSION_CACHED_CURSORS initialisation parameter relate to ACS? |
|
How does the OPEN_CURSORS initialisation parameter relate to ACS? |
|
ACS and Bind Variables |
|
Does bind peeking play a role in ACS? |
|
What is the difference between bind aware and bind sensitive? |
|
Why is ACS restricted to 14 bind variables? |
|
Why are there hints to enable/disable bind aware features? |
|
Can we enable BIND_AWARE hint in any way for all connections from a user or service? |
|
Should ACS be disabled if the Bind Variable Selectivity Changes too frequently? |
|
What does it mean for ACS when bind aware is true, but bind sensitive is false? |
|
ACS and Histograms |
|
Are histograms always needed for ACS? |
|
If there is are histograms, how does Oracle determine that a SQL statement is bind sensitive? |
|
ACS and Query Optimization |
|
Can ACS choose a Bad Plan when there is a better one available? |
|
Can ACS make the CBO choose a bad plan? |
|
Does ACS impact SQLT output? |
|
ACS and Sharing of Cursors |
|
Once ACS has made a SQL statement non-shareable, will that plan never be used? |
|
Is there a danger of generating a high number of version counts with ACS enabled? |
|
How do SQL profiles play a role in ACS ? |
|
ACS and SPM |
|
What is the relationship between ACS and Sql Plan Management (SPM) ? |
|
If I have some plan baselines that I am happy with, then I enable ACS which creates some plans which look promising, how does SPM and ACS interract? |
|
What would be the impact of ACS we're NOT using SPM and have Statistics locked |
|
Using SPM we can pin a good plan, can this be done in case of a situation demanding better plan (among the child cursors) arises with ACS.... |
|
Discuss Adaptive Cursor Sharing |
References |
Oracle Server - Enterprise Edition - Version 11.1.0.6 and later
Oracle Server - Personal Edition - Version 11.1.0.6 and later
Oracle Server - Standard Edition - Version 11.1.0.6 and later
Information in this document applies to any platform.
Thisseries of Questions and Answers was generated from the Q&A Session for"Understanding Adaptive Cursor Sharing (ACS) with a Test Case and liveDemo" Webcast. This recording for this webcast can be accessed in thefollowing document:
Document 740966.1 Advisor Webcasts: Current Schedule and Archived recordings
Theadaptive cursor sharing feature enables a single statement that contains bindvariables to use multiple execution plans. Cursor sharing is"adaptive" because the cursor adapts its behavior so that thedatabase does not always use the same plan for each execution or bind variablevalue.
Would you like to explorethis topic further with other Oracle Customers, Oracle Employees, and IndustryExperts?
Clickhere to join the discussion where you can ask questions, get help from others,and share your experiences with this specific article.
Discover discussions about other articles and helpful subjects by clicking here to access the main My Oracle Support Community page for Database Tuning.
Themain documents about ACS can be found here:
Document 1115994.1 Introduction to Adaptive Cursor Sharing concepts in 11G andmutimedia demo [Video]
Document 836256.1 Adaptive Cursor Sharing in 11G
Document 740052.1 Adaptive Cursor Sharing: Overview
Oracle® Database Performance Tuning Guide
11g Release 2 (11.2)
Part Number E16638-06
11.1.3.1 Adaptive Cursor Sharing
http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#CIHIGAHB
Youcan find links to Technical White Papers and Blogs for the Oracle Optimizer,including ACS, here:
Document 1337116.1 White Papers and Blog Entries for Oracle Optimizer
ACSis based on actual rows not estimated rows.
Statisticslevel set to all is not required, it is only there so we can see the actualrows in the execution plan.
ACSwill increase the shared pool requirements but it is difficult to say by howmuch since it is dependent on the amount of variability in the plans in theapplication
No
No.The ACS information is unique to each node and is not shared from instance toinstance.
Yes.ACS will work on the SQL started within PL/SQL
NotSimilar.
If the application uses binds then EXACT is fine If literals and we want to useACS then FORCE.
Developmentare considering this and it may happen in the future.
No.
No separate license is required See:
Document 1361401.1 Where to Find Information About Performance Related Features
Yes.
ACS is a standard feature of Personal, Standard and Enterprise Editions. See:
Document 1361401.1 Where to Find Information About Performance Related Features
CURSOR_SHARING= FORCE converts all SQL statements that do not use bind variables to containbind variables so that they can be shared.
CURSOR_SHARING = EXACT performs no literal replacement so ACS will work only onSQL that was originally written to include bind variables.
ACS works on all SQL containing bind variables regardless of whether they werein the original SQL or generated by cursor_sharing = FORCE.
Adaptive cursor sharing is independent of the CURSOR_SHARING initializationparameter and is equally applicable to statements that contain user-defined andsystem-generated bind variables.
Oracle® DatabasePerformance Tuning Guide 11g Release 2 (11.2)
Part Number E16638-07
Section 7.3.10.2 When to Set CURSOR_SHARING to a Nondefault Value
http://docs.oracle.com/cd/E11882_01/server.112/e16638/memory.htm#PFGRF94345
and
Section 11.1.3.1 Adaptive Cursor Sharing
http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#CIHIGAHB
Yes,as long as the queries contain bind variables. Queries with literals are notcandidates for ACS.
CURSOR_SHARING= FORCE is a workaround to make an application scalable that otherwisewould not be because of literals. It is not however the optimal solution (whichis to write the application with bind variables in the first place), it is aworkaround - we are trying to fix a problem with aparameter. CURSOR_SHARING = FORCE replaces literals with binds. Pre-11g(i.e. with no ACS) queries with bind variables were constrained to a single executionplan per SQL. With 11g and ACS we can have multiple execution plans. So thereare no specific negative effects of CURSOR_SHARING = FORCE . With ACS you mayget more cursors than without ACS but these should be for different plans basedon the different values and their selectivities.
No.
ACS will not be used because there are no binds in the query.
TheSESSION_CACHED_CURSORS parameter allows you to specify the number of cursors tocache within an individual session. This can help performance where queries arerepeated within that session. See:
Document 30804.1 Init.ora Parameter "SESSION_CACHED_CURSORS" Reference
Oracle® Database Reference
11g Release 2 (11.2)
Part Number E25513-03
SESSION_CACHED_CURSORS
http://docs.oracle.com/cd/E11882_01/server.112/e25513/initparams229.htm#REFRN10195
Whetheror not you need a larger session cache with ACS depends on your application andhow many extra cursors are being stored with ACS as compared to without. It isdifficult to generalise and while ACS is likely to increase the number ofcursors for bind aware cursors, it does not necessarily affect all queries andit may not increase the number of cursors significantly overall. If it does,then increasing the cache may help but only if individual sessions re-use thesame cursors.
If, for example, you have 100 different child cursors created by ACS and anindividual session only use one of these within a particular session thenadditional session caching would be unlikely to help. If however the sessionused bind variable values such that all 100 were used then additional sessioncaching may prove beneficial.
Generally, the default value should be sufficient, but if you want to checkyour usage then we would suggest using a script similar to the following tomeasure the usage for a representative set of session and use that as a basisfor any decision:
Document 208857.1 SCRIPT - to Set the 'SESSION_CACHED_CURSORS' and 'OPEN_CURSORS'Parameters Based on Usage
Ifyou find that you are using more cursors than you have cached and that, upontesting, a higher value is beneficial for your application, then a higher valuecan be set.
TheOPEN_CURSORS parameter has nothing to do with ACS. It limits the number ofcursor that can be kept open in a session at the same time. Its purpose is toprevent a session from opening an excessive number of cursors. Refer toReference Manual for details:
Oracle® DatabaseReference 11g Release 2 (11.2)
Part Number E25513-03
OPEN_CURSORS
http://docs.oracle.com/cd/E11882_01/server.112/e25513/initparams161.htm#REFRN10137
Yes,it is one of the pre-requisites. ACS needs to know the bind variable value sothat it can use column histograms to determine the selectivity of the bindvariables that is uses to determine if extra plans are required.
Bindsensitive means that a query contains bind variables that are sensitive todifferent plans when the bind values are changed. For example, for a particularbind variable, if data is skewed then the number of rows returned by ValueAmight be 10 but for ValueB is 10,000. In this case a different plan may beappropriate for each value. This query would be bind sensitive in that the planchosen is sensitive to the values of the bind variables supplied when the queryis executed.
Bind aware means that the statement has moved into ACS and is a candidate formultiple plans according to different bind variables. This status is achievedby some checks to ensure that cursors are not moved into ACS unless they aredeserving of it so as to avoid using extra space in the shared poolunnecessarily.
Developmentare wary of ACS taking up too much space with large numbers of large cursors sothey chose a limit of 14 which is appropriate for the vast majority of queries.If this limit is exceeded then the SQL will never become bind sensitive.
ACSis conservative in making statements bind aware. If ACS made all queries movefrom bind sensitive to bind aware in every case the shared pool would beflooded with ACS cursors and there would be no benefit over creating a cursorfor every different bind value. There can be cases where the order that SQL isexecuted can mean that the statement sometimes becomes bind aware and othertimes does not. If we want it to be bind aware we can use the hints.
No.
It would be unlikely that you would want to do that because it could impact toomany sql statements. It is better to use on only a few sql statements for whereit provides a benefit than globally where space and CPU would be wasted.
No.
ACS is designed to handle changes in bind variable values.
Lets consider that we have SQL with a bind variable in a predicate against acolumn with a histogram and the bind value is changed many times. In this casethe selectivity may be different for all or many (or none even) of thes values.When each value is evaluated, if the selectivity is not within any of theranges of the existing selectivities already recorded against a bind awarequery there will be some overhead because it will have to make the child cursornon-shareable and create a new child cursor copy the selectivity profile andincrease the range of it. This overhead occurs primarily in the ramp up phase.Once the system is stable then the selectivities are less likely to be out ofrange it should just pick plans according to the selectivity of the predicate.
Thisis not a normal situation. For a SQL to be bind aware it must first have beenbind sensitive. If you have this particular case then we suggest you open a SRwith the details.
Histogramsare required for ACS to work upon SQL with equality predicates. Withouthistograms the selectivity for an equality predicate against a column is 1 /Number of distinct values in the column. This is the same for all values andthus ACS could not differentiate between plans based on bind value. SQL withrange predicates (and LIKE) can work regardless of histogram because differentselectivities can be estimated for different values provided compared to theposition of the values relative to the high and low values in the column.Obviously with histograms this information will be more accurate.
WithEquality predicates it cannot.
However a SQL statement with range predicates ( > < >= etc) hasdifferent selectivity regardless of the presence of histograms since the optimizergenerates selectivity estimates from the low/high column values
ACScreates plans based upon selectivity ranges. It is still possible that a badplan could be chosen for a particular selectivity range but it is likely to bebetter overall than relying on a single plan for all ranges.
No.
ACS simply triggers a new hard parse based upon certain trigger conditions. Itis still up to the optimizer to determine the plan based on the statistics itis provided.
SQLTwill report information regardless of whether ACS used or not. SQL contains anAdaptive Cursor Sharing section:
which will be populated with various ACS related information if ACS is used.
Thechild cursor will not be used but the plan may be re-generated in other childcursor if it is re-parsed. A Child Cursor becomes non-shareable because nowthat ACS is enabled and active for this cursor, the new ACS Bind Aware plansneed to be used.
HighVersion Counts can be an issue regardless of ACS. That said however ACS doeshave potential to generate more cursors than simply sharing 1 cursor for alldifferent bind values without it. It is considerably better than having adifferent cursor for every single values like you would with literals. Thenumber of cursors with ACS should stay under a controlled number (you would notexpect hundreds of cursors with ACS) _ and is going to be somewhere between 1cursor (bind variables) and 1 cursor for every value (literals) but tendingtowards the lower end of that due to the selectivity range model and thelikelihood that there are probably a small number of good plans for each SQLstatement.
SQLProfiles adjust CBO calculations and impact the final plan. ACS doesn't impactthe final plan generated by the optimizer. It manages whether different plansare required to handle different bind variable values. The goal of ACS is tomake sure that a new hard parse is triggered when a new plan is required.
ACShelps with in plan flexibility.
SPM helps with plan stability.
ACS allows there to be different plans for the same cursor with bind variables,but limits this based upon the selectivity of those bind variables rather thanhaving a different plan for every bind (as you would with literals).
SPM allows you to fix and manage access paths for queries so that only alimited number of verified and accepted plans are available for queries so asto avoid 'nasty suprises' such as the generation of new bad plan.
Ifyou are happy with a new plan then you need to determine whether to use them ornot and accept the new plans. the new plans will not be executed unless theyare accepted.
ACScan work regardless of SPM or locked statistics. Different set of bind valuescould get still get different plans.
With SPM, plans that have not been accepted are not so ACS will simply generateplans that are waiting to be accepted or rejected. The standard SPM plan willbe used until that happens.
With locked statistics you could still get different plans with different bindvariable values until the stored ACS plans have reached a certain level ofmaturity depending on the relative selectivities of the bind variable values.
Yes.The cursors generated by ACS will not have been accepted by SPM so SPM stillapplies.
The window below is a live discussion of this article (not ascreenshot). We encourage you to join the discussion by clicking the"Reply" link below for the entry you would like to provide feedbackon. If you have questions or implementation issues with the information in thearticle above, please share that below.
Adaptive Cursor Sharing: Worked Example [ID 836256.1] |
To Bottom |
Modified:19-Dec-2012Type:BULLETINStatus:PUBLISHEDPriority:3 |
|
Inthis Document
Purpose |
Scope |
Details |
References |
Oracle Server -Enterprise Edition - Version 11.1.0.6 and later
Information in this document applies to any platform.
***Checked for relevance on 01-Aug-2011***
Todiscuss the Adaptive Cursor Sharing in feature in 11G using a simple testcase
SupportEngineers
DBAs
Introduction
It isa common problem on previous releases of the database that , when bindvariables are used, the initial plan can be suboptimal due to the fact that (a)future values used in future executions share the initial plan and (b) thefirst set of binds used may not be representative of the majority of executionsand therefore that initial plan could be considered "bad" in thecontext of what is best for most executions.
11G introducesthe concept of Adaptive Cursor Sharing. The idea now is to no longerblindly share plans but do so only if itis believed the bind values will not degrade a currently stored plan
Testcase
Thefollowing testcase is needed to explain the behaviour
create table acs_test (col1 varchar2(1),col2 varchar2(1),col3varchar2(1));
insert into acs_test values ('A','A','X');
insert into acs_test values ('B','B','X');
begin
for i in 1..20 loop
insert into acs_test values ('A','C','X');
end loop;
end;
/
begin
for i in 1..20 loop
insert into acs_test values ('B','D','X');
end loop;
end;
/
begin
for i in 1..958 loop
insert into acs_test values ('C','D','X');
end loop;
end;
/
create index acs_test_idx on acs_test(col1,col2);
execute dbms_stats.gather_table_stats(NULL,'acs_test',method_opt=>'FOR ALLCOLUMNS SIZE 254');
...thereare now 1000 rows with the following counts
select col1, count(*) from acs_test group by col1;
C COUNT(*)
- ----------
A 21
B 21
C 958
SQL> select col2,count(*) from acs_test group by col2;
C COUNT(*)
- ----------
D 978
A 1
B 1
C 20
Theselectivity of each column value is:
COL1
A ->21/1000 = 0.021
B -> 21/1000 = 0.021
C -> 958/1000 = 0.958
COL2
A-> 1/1000 = 0.001
B -> 1/1000= 0.001
C -> 20/1000 = 0.020
D -> 978/1000 = 0.978
Discussion
Thefollowing testcase will be used for the purpose of this discussion:
var b1 varchar2(128);
var b2 varchar2(128);
begin
:B1 := <value>;
:B2 := <value>;
end;
/
select * from acs_test where col1=:B1 and col2=:B2;
Theselectivities are central to adaptive cursor sharing. The basic concept is that, in the testcase example, a cube is stored centered around an x/y axiswhere x=sel of col1 and y=sel of col2. If future bind values are such that thex/y for those fall outside that cube it won't share it and willcreate a new cursor and possibly a new plan so there is now 2 suchcubes. If the 3rd execution has bind values that fall inside either of thecubes then they share that child (and therefore it's plan) , otherwise ittoo will generate a new child/new cube/new plan
Runthe cursor for the first time and use :B1 = 'A' and :B2 = 'A'
Thefirst execution will obviously cause a hard parse. If there is ahistogram, bind peeking is enabled and the cursor uses binds(which it does) then the sql will be marked as bind sensitive. This can beseen here:
select child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA,plan_hash_value
from v$sql
where sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA PLAN_HASH_VALUE
------------ ---------- ----------- -- -- ---------------
0 1 30 Y N 2647430641
Notethat the cursor is not currently bind aware. This is because,presently there has been 1 execution and therefore it is not yetknown if the bind values are such that they will cause different selectivitiesfor different values when executed. What has happened in this first executionis that information related to the bind values and the execution stats arestored in the cursor.
Thecurrent execution statistics for the cursor can be seen using:
SQL> select * from v$sql_cs_statistics where sql_id='19sxt3v07nzm4';
ADDRESS HASH_VALUE SQL_ID CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS
-------- ---------- ------------- ------------ ------------------- - ----------
ROWS_PROCESSED BUFFER_GETS CPU_TIME
-------------- ----------- ----------
324A9D84 3229253220 19sxt3v07nzm4 0 1498426793 Y 1
2 30 0
Thefirst execution returned a single row - the selectivity of 'A'/'A' was 0.21/0.01
Theplan it uses is
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100) | |
| 1 | TABLE ACCESS BY INDEX ROWID | ACS_TEST | 1 | 6 | 2 (0) | 00:00:01 |
| 2 | INDEX RANGE SCAN | ACS_TEST_IDX | 1 | | 1 (0) | 00:00:01 |
--------------------------------------------------------------------------------------------
If itis run again using :B1='C' and :B2='D' this will return 958 rows theselectivity is now 0.958/0.978
Ituses the same plan. The buffer gets rises significantly (From 30 to 163)
select child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA,plan_hash_value
from v$sql
where sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA PLAN_HASH_VALUE
------------ ---------- ----------- -- -- ---------------
0 2 163 Y N 2647430641
Thecursor is still not bind aware because this high buffer get run may be aone-off. Run it once more to force a change in behaviour:
select child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA,plan_hash_value
from v$sql
where sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA PLAN_HASH_VALUE
------------ ---------- ----------- -- -- ---------------
0 2 163 Y N 2647430641
1 1 68 Y Y 3194050402
Note thereis now a new child (1) and this is now marked as bind_aware. The plan forthe child has changed to hash_value 3194050402 which is :
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100) | |
| 1 | TABLE ACCESS FULL | ACS_TEST | 936 | 5616 | 3 (0) | 00:00:01 |
------------------------------------------------------------------------------
Theinformation about each bind value used for each child is stored inV$SQL_CS_SELECTIVITY. This view is only populated when the cursor becomes bindaware
SQL> select CHILD_NUMBER,PREDICATE,RANGE_ID,LOW,HIGH
from v$sql_cs_selectivity
where sql_id = '19sxt3v07nzm4';
CHILD_NUMBER PREDICATE RANGE_ID LOW HIGH
------------ ---------------------------------------- ---------- ---------- ----------
1 =B2 0 0.879750 1.075250
1 =B1 0 0.861750 1.053250
Rerunthe first SQL again (binds 'A','A'):
SELECT child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA, plan_hash_value
FROM v$sql
WHERE sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA PLAN_HASH_VALUE
------------ ---------- ----------- -- -- ---------------
0 2 163 Y N 2647430641
1 1 68 Y Y 3194050402
2 1 4 Y Y 2647430641
Thereis now yet another child and another plan . This is because thecursor is now bind aware and would look to see if it could share child 1,see the ranges for the binds are outside of those for the stored ranges(B1 is 'A' which is a selectivity of 0.021 and notbetween 0.861750 and 1.05320 ). The range of values required to meet thecriteria for sharing is stored with each new child:
SQL> SELECT child_number, predicate, range_id, low, high
FROM v$sql_cs_selectivity
WHERE sql_id = '19sxt3v07nzm4';
CHILD_NUMBER PREDICATE RANGE_ID LOW HIGH
------------ ---------------------------------------- ---------- ---------- ----------
2 =B2 0 0.000900 0.001100
2 =B1 0 0.018900 0.023100
1 =B2 0 0.879750 1.075250
1 =B1 0 0.861750 1.053250
Child2 B1 was 0.021 - the range is evenly spread around it (+/- 0.0021) ie 10%
LikewiseChild 1 B1 was 0.958 and the range is +/- 10% too
So -any future bind pairs will need to be within BOTH ranges. If any are outsidethe range then a new child will be created. Running a combination ofChild1 and Child2. ie, set B1 to 'A' and B2 to 'D' should create a new child asit cannot share any current one. This returns no rows and creates a new child
SELECT child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA, plan_hash_value
FROM v$sql
WHERE sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA PLAN_HASH_VALUE
------------ ---------- ----------- -- -- ---------------
0 2 163 Y N 2647430641
1 1 68 Y Y 3194050402
2 1 4 Y Y 2647430641
3 1 2 Y Y 2647430641
Theplan for the Child is the same as that of Child2.
SQL> SELECT child_number, predicate, range_id, low, high
FROM v$sql_cs_selectivity order by child_number,range_id,predicate
WHERE sql_id = '19sxt3v07nzm4';
CHILD_NUMBER PREDICATE RANGE_ID LOW HIGH
------------ ---------------------------------------- ---------- ---------- ----------
1 =B1 0 0.861750 1.053250
1 =B2 0 0.879750 1.075250
2 =B1 0 0.018900 0.023100
2 =B2 0 0.000900 0.001100
3 =B1 0 0.018900 0.023100
3 =B2 0 0.879750 1.075250
3 =B1 1 0.018900 0.023100
3 =B2 1 0.000900 0.001100
Something,unexpected until now, happened. There are 4 entries for Child3. There is a pair of RANGE_IDs for each bind. Note that theLOW/HIGH range for RANGE_ID 1on B1/B2 is the same as that of Child 2 (where weran with 'A'/'A'). If the execution with 'A'/'A' is run again now it can be seenthat it no longer uses Child 2 but , instead uses Child 3.
SELECT child_number, executions, buffer_gets,
is_bind_sensitive BS, is_bind_aware BA, plan_hash_value
FROM v$sql
WHERE sql_id = '19sxt3v07nzm4';
CHILD_NUMBER EXECUTIONS BUFFER_GETS B B PLAN_HASH_VALUE
------------ ---------- ----------- - - ---------------
0 2 137 Y N 2647430641
1 1 67 Y Y 3194050402
2 1 4 Y Y 2647430641
3 2 6 Y Y 2647430641
So -what has happened is that Child3 , because it has used the same plan as Child2has made that child redundant and the range_ids for Child3 are :
RANGE_ID 0-- Original Ranges as it would have been if the plan was new.
RANGE_ID 1 -- The incorporation of Child 2s ranges so anything found in thatrange can use this new Child.
Adaptive Cursor Sharing: Overview [ID 740052.1] |
To Bottom |
Modified:25-Mar-2013Type:REFERENCEStatus:PUBLISHEDPriority:3 |
|
Inthis Document
Purpose |
Scope |
Details |
|
Introduction |
|
Advantages and Disadvantages of Adaptive Cursor Sharing |
|
Advantages of Adaptive Cursor Sharing |
|
Disadvantages of Adaptive Cursor Sharing |
|
Extended Cursor Sharing (Bind Sensitivity) |
|
Adaptive Cursor Sharing (Bind Aware) |
|
Monitoring |
|
Known Issues with Excessive Child Cursors |
References |
Oracle Database - Enterprise Edition - Version 11.1.0.6 and later
Information in this document applies to any platform.
Thepurpose of this document is to provide an overview to the Adaptive CursorSharing (ACS) feature that was introduced in 11g
Thedocument contains a basic overview and background as well as issues thatcustomers should be aware of.
Withthe introduction of the Cost Based Optimizer (CBO) a number of changes weremade to calculate the selectivity of a predicate, which in turn affected howthe query was optimized. The selectivity was based on the number ofdistinct values for a given column or a predefined percentage of rows dependingon the relational operator that was used. For more details on predicateselectivity see:
Document 68992.1 Predicate Selectivity
Thisworked well for data that was evenly distributed but had limitations inapplications where data was skewed.
With 9i, a new feature "Bind Peeking" was introduced to try to getaround the issues associated with the selectivity of a bind variable. During hardparsing of a query using bind variables, the binds are "peeked at"and selectivity is generated based on the bind and the underlying columnstatistics. This method is successful but if the bind selectivity of theinitial execution of a statement varied from the selectivity of subsequentexecutions with different sets of binds this could sometimes lead to plansbeing generated that were not representative of the general query usage andwhich performed poorly.
InOracle 10g, this was especially noticeable since the default statisticgathering methodology changed to gather histograms automatically. This meantthat selectivity previously generated based on the number of distinct valueswas now generated based on histograms. This gave the optimizer betterinformation about the distribution of skewed data, the impact of which beingthat the first execution of a query using binds that were representative of thegeneral query usage was particularly important. For more information on thissee:
Document 387394.1 Query using Bind Variables is suddenly slow
Document 430208.1 Bind Peeking By Example
InOracle 11g, Adaptive Cursor Sharing was introduced to provide a solution tothese issues. Adaptive Cursor Sharing monitors the execution statisticsfor candidates queries and makes it possible for the same query to generate anduse different execution plans for different set of binds values. See:
Oracle® DatabasePerformance Tuning Guide
11g Release2 (11.2)
Part Number E16638-07
11.1.3.1 Adaptive Cursor Sharing
http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#PFGRF95174
https://blogs.oracle.com/optimizer/entry/why_are_there_more_cursors_in_11g_for_my_query_containing_bind_variables_1
https://blogs.oracle.com/optimizer/entry/update_on_adaptive_cursor_sharing
https://blogs.oracle.com/optimizer/entry/explain_adaptive_cursor_sharing_behavior_with_cursor_sharing_similar_and_force
Adaptivecursor sharing is a solution to provide the shareability of binds, with theplan adaptability of literals.
With adaptive cursor sharing the database can adapt execution plans based onthe selectivity of values used in bind variables. This resolves the situationwhere the plan used for one set of bind variables is inappropriate for anotherset.
Previously, workarounds employed would either use literal values instead ofbinds, which could lead to excessive hard parsing, or apply a fixed plan thatcould cause performance issues.
Theremay be some extra overhead associated with Adaptive Cursor Sharing:
Thefirst step towards ACS is Extended Cursor Sharing - where a query is recognisedas "Bind Sensitive". This means that the best plan for a query haspotential to be different according to the bind variables supplied to it. Ineffect this just means the cursor is being monitored to see if it should bemade bind aware.
Acursor is marked as Bind Sensitive if:
· query is executed with bind peeking
· binds using any of the following relational operators = < ><= >= != or a user defined bind operator e.g.contains(e.job,:job,1)>0,
From 11.2.0.2 the "LIKE" operator is also supported.
· A histogram exists on the column containing the bind value.
Inother words, a cursor is marked Bind Sensitive if a change in the bind variablevalue may lead to a different plan.
Apart from checking for a valid operator there are also a number of subsequentbind sensitivity checks that need to be performed before it can be marked asbind sensitive. If any of these checks fail, the cursor will not be marked asbind sensitive and adaptive cursor sharing will not occur and Extended CursorSharing will be disabled :-
SQLPlan Baselines are designed to work with Adaptive Cursor Sharing. Anyvalid enabled SQL Plan Baselines Plans can be used by Adaptive CursorSharing. This means if you have more than one enabled baseline for agiven SQL statement ACS can use one or more of those baselines at the sametime.
How do adaptive cursor sharing andSQL Plan Management interact?
When all the criteria are met the cursor is marked as bindsensitive and a "sharing context" containing information aboutexecution statistics of the cursor is created and stored against the cursor.
Cursors that are marked as bind-sensitive can been identified by the columnIS_BIND_SENSITIVE having a value "Y" in V$SQL or V$SQLAREA.
Ifthere is significant variation in the row source cardinality for executions ofthe same sql statement in consecutive executions a cursor will be marked asbind aware.
For more information about this please see :-
Document 836256.1 Adaptive Cursor Sharing: Worked Example
Document 1115994.1 Introduction to Adaptive Cursor Sharing Concepts and MultimediaDemo [Video]
https://blogs.oracle.com/optimizer/entry/why_are_there_more_cursors_in_11g_for_my_query_containing_bind_variables_1
V$SQL can be used to see whether a cursor is_bind_sensitive,is_bind_aware, or is_shareable.
Bind context information can be viewed via V$SQL_CS_SELECTIVITY, V$SQL_CS_STATISTICSand V$SQL_CS_HISTOGRAM
V$SQL_CS_SELECTIVITY displays the valid selectivity ranges for a childcursor in extended cursor sharing mode.
A valid range consists of a low and high value for each predicate containingbinds. Each predicate's selectivity (with the current bind value) must fallbetween the corresponding low and high values in order for the child cursor tobe shared.
V$SQL_CS_STATISTICS contains the raw execution statistics used by themonitoring component of adaptive cursor sharing.
A sample of the executions is monitored. This view shows which executions weresampled, and what the statistics were for those executions. The statistics arecumulative for each distinct set of bind values.
V$SQL_CS_HISTOGRAM summarizes the monitoring information stored by adaptivecursor sharing.
This information is used to decide whether to enable extended cursor sharingfor a query. It is stored in a histogram, whose bucket's contents areexposed by this view.
Thereis a possibility that Adaptive Cursor Sharing may compound problems in whichexcessive numbers of child cursors are generated. This may lead toperformance degradation as large numbers of child cursor can put space pressureon the shared pool and may also lead to an increase in mutex X waits for thatcursor.
Checklist to avoid known issues
1. Ensure that cursor_sharing is not set to SIMILAR. In 11g this settingis not recommended and is deprecated in future releases.
Document 1169017.1:ANNOUNCEMENT:Deprecating the cursor_sharing = 'SIMILAR' setting
2. Ifthere are high version counts check v$sql_shared_cursor and search My OracleSupport for notes that may allude to the cause of the excessive cursors.
Document 438755.1 : Formated V$SQL_SHARED_CURSOR Report by SQLID or Hash Value
Ifthere are still excessive child cursors, then Oracle Support should becontacted to assist with diagnosing the issue.
NOTE:1518681.1 - FAQ: Adaptive Cursor Sharing (ACS) Frequently Asked Questions
NOTE:13456573.8 - Bug 13456573 - Many child cursors / ORA-4031 with largeallocation in KGLH0 using extended cursor sharing
NOTE:6644714.8 - Bug 6644714 - High number of child cursors with adaptive cursorsharing
NOTE:430208.1 - Bind Peeking By Example
NOTE:68992.1 - Predicate Selectivity
NOTE:1169017.1 - ANNOUNCEMENT: Deprecating the cursor_sharing = 'SIMILAR' setting
NOTE:387394.1 - Query using Bind Variables is suddenly slow
NOTE:1115994.1 - Introduction to Adaptive Cursor Sharing Concepts and MultimediaDemo [Video]
NOTE:836256.1 - Adaptive Cursor Sharing: Worked Example
Predicate Selectivity [ID 68992.1] |
To Bottom |
Modified:08-May-2012Type:FAQStatus:ARCHIVEDPriority:3 |
|
Purpose
~~~~~~~
This article explains how the CBO determines the selectivity for various
predicates.
Audience
~~~~~~~~
This article is aimed at Application Developers, DBA's and support analysts
interested in understanding how the CBO determines how selective a
particular access path is.
Selectivity
~~~~~~~~~~~
Selectivity is a measure of the proportion of a row source retrieved by
application of a particular predicate or combination of predicates.
Within the Oracle kernel it is expressed as a value between 0 and 1.
The closer the value is to 0 the more selective the predicate is.
Selectivity is only used by the CBO.
Basic Selectivity formula:
~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of records satisfying a condition
Selectivity = -----------------------------------------
Total Number of records
In the optimizer, selectivity is used to compare the usefulness of various
predicates in combination with base object costs.
Knowing the proportion of the total data set that a column predicate defines
is very helpful in defining actual access costs.
By default, column selectivity is based on the high and low values and the
number of values in the column with an assumption of even distribution of
data between these two points.
Histogram data can give better selectivity estimates for unevenly distributed
column data. There is more discussion regarding Histograms later.
Selectivity is also used to define the cardinality of a particular row source
once predicates have been applied. Cardinality is the expected number of rows
that will be retrieved from a row source. Cardinality is useful in determining
nested loop join and sort costs. Application of selectivity to the original
cardinality of the row source will produce the expected (computed) cardinality
for the row source.
Glossary of Terms:
~~~~~~~~~~~~~~~~~~
NDV Number of Distinct Values
Cardinality Number of rows
Selectivity Proportion of a dataset returned by a particular predicate(or
group of predicates)
In the following illustrations there are 2 tables (T1 & T2) with columns (c1) and (c2) respectively.
Selectivities:
~~~~~~~~~~~~~~
Without histograms
~~~~~~~~~~~~~~~~~~
c1 = '4076' 1/NDV
c1 > '4076' 1 - (High - Value / High - Low)
c1 >= '4076' 1 - (High - Value / High - Low) + 1/NDV
c1 like '4076' 1/NDV
Join selectivity
~~~~~~~~~~~~~~~~
The selectivity of a join is defined as the selectivity of the most selective
join column adjusted by the proportion of not null values in each join column.
Sel = 1/max[NDV(t1.c1),NDV(t2.c2)] *
( (Card t1 - # t1.c1 NULLs) / Card t1) *
( (Card t2 - # t2.c2 NULLs) / Card t2)
Bind Variable selectivity
~~~~~~~~~~~~~~~~~~~~~~~~~
Bind variables present a special case because the optimizer has no idea what
the bind variable value is prior to query optimization. This does not present
a problem with equality predicates since a uniform distribution of data is
assumed and the selectivity is taken as 1/NDV for the column. However for
range predicates it presents a major issue because the optimizer does not
know where the range starts or stops. Because of this the optimizer has to
make some assumptions as follows:
c1 = :bind1 1/NDV
c1 > :bind1 Default of 5%
c1 >= :bind1 Default of 5%
c1 like :bind1 Default of 25%
For more information on bind variables see Note:70075.1
Selectivity With Histograms
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Histograms provide additional information about column selectivity for
columns whose distribution is non uniform. Histograms store information about
column data value ranges. Each range is stored in a single row and is often
called a 'bucket'. There are 2 different methods for storing histograms in
Oracle. If there are a small number of distinct
column values (i.e. less than the number of buckets), the column value
and the count of that value is stored. If not then a series of endpoints
are stored to enable more accurate selectivity to be determined.
The first method allows the accurate figures to be used. However with
inexact histograms the terms popular and non-popular value are introduced
and are used to help determine selectivity. A popular value is a value that
spans multiple endpoints whereas a non-popular value does not.
See Note:72539.1 for more information on histograms.
Exact histograms
~~~~~~~~~~~~~~~~
c1 = '4706' count of value '4076' / Total Number of Rows
c1 > value count of values > '4076' / Total Number of Rows
InExact Histograms
~~~~~~~~~~~~~~~~~~
col = pop value # popular buckets / # buckets
col = non pop (Density)
col > value # buckets > value / # buckets
Rules for combining selectivity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let P1 and P2 be 2 distinct predicates of query Q
P1 AND P2
S(P1&P2) = S(P1) * S(P2)
P1 OR P2
S(P1|P2) = S(P1) + S(P2) -[S(P1) * S(P2)]
Index Selectivity for concatenated indexes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Starting with 10.2, when a concatenated index, with all its columns having
equality predicates, is used as an access path, the optimizer uses 1/NDK as
the selectivity (where NDK is the number of distinct keys in the index).
On 9.2.0.7 and 9.2.0.8 this may be enabled with event 38060 level 1.
On 10.1.0.4 and 10.1.0.5 this may be enabled with event 38059 level 1.
On 10.2 adjustments will be made to the selectivity to account for nulls
in the index keys. This also occurs on 10.1.0.5 (with event 38059.)
Join cardinality
~~~~~~~~~~~~~~~~
Card(Pj) = Card(T1) * Card(T2) * Sel(Pj)
NOTE:70075.1 - Use of bind variables in queries (Pre 9i)
NOTE:72539.1 - Interpreting Histogram Information