Summary
Despite being correctly configured (parameters, statistics, ...), the Oracle Cost Based Optimizer (CBO) or Rule Based Optimizer (RBO) chooses an unsuitable access path for an SQL statement, and this leads to an unnecessarily long runtime.
There are several possible causes of long SQL statement runtimes. This note also describes those bugs and features associated with the Oracle optimizer that may frequently cause problems in the SAP environment.
For an overview of other possible causes of poor database performance, see Note 618868.
In addition to the solutions mentioned below, you generally have the option of forcing the Optimizer to use the optimal access path by entering specific database hints (Notes 129385 and 130480). Another general option for influencing the CBOs is the postprocessing of statistics (Note 724545). However, this approach should only be seen as a temporary workaround in most cases, rather than a permanent solution.
Note 750631 describes the basic procedure for using the CBO for cost calculation.
Note that you should first make all changes in a non-production environment to check for possible side effects. It is of no use, if tuning ONE SQL statement leads to serious performance problems with other statements.
- 1. RBO: Columns from index item 3 are not evaluated, if they are specified with IN or OR
- 2. RBO: The second index column is not analyzed if it is defined with OR and LIKE
- 3. RBO: The optimum index is not used because an equivalent index exists
- 4. RBO / CBO: CBO instead of RBO is used for access
- 5. CBO: Index columns after a range specification are analyzed only under certain conditions
- 6. CBO: The optimum index is not used because an equivalent index exists
- 7. CBO: The optimum index is not used if a FIRST_ROWS hint is used and the first key field is not specified with "="
- 8. CBO: The optimum index is not used if the relevant key fields have few different values
CBO: Sort Merge Join or Hash Join instead of Nested Loop Join
CBO: Index Full Scan instead of Index Range Scan if the relevant key fields have few different values
- 9. CBO: The optimum index is not used if key fields are specified with long OR operations
- 10. CBO: The optimum index is not used if long IN lists are used in key fields
- 11. CBO: SORT MERGE JOIN in statements with "ROWNUM <"
- 12. CBO: The optimum index is not used in View or Join with OR operations
- 13. CBO: The optimum index is not used if different column values are identical in the first 32 characters
- 14. CBO, Oracle <=9.2.0.5: Index given preference for "=" and columns with 1 distinct value.
- 15. CBO: Index is not used if NULLABLE=Y for all indexed columns
- 16. CBO, Oracle >=9.2.0.4: Incorrect index is used for FIRST_ROWS hint in connection with ORDER BY
- 17. CBO, Oracle <=9.2.0.5: Index given preference for BETWEEN and columns with two distinct values.
- 18. CBO: Index with range on the first column is not used
- 19. CBO, Oracle 9i: No Index Range Scan with OR, Range and AND EXISTS
- 20. CBO, Oracle 9i <= 9.2.0.6: No Index Skip Scan despite optimal costs
- 21. CBO, Oracle 9i: Unsuitable access path (Full Table Scan, Index Full Scan, ...) in interlocking OR operations
- 22. CBO: No Index Skip Scan using ranges
- 23. CBO, Oracle 9i <= 9.2.0.6, histograms, literals: Incorrect costs if range begins or ends on the endpoint value of a histogram.
- 24. CBO: Long runtimes if there are several range specifications on one index column
- 25. CBO, Oracle 9.2.0.7, 10g <= 10.2.0.2: Bind Value Peeking: Optimal costs for unsuitable indexes.
- 26. CBO, Oracle 9i: Incorrect values for estimated rows in joins
- 27. CBO, DBMS_STATS, histograms, Oracle <= 9.2.0.5: Incorrect values for estimated rows, merge join cartesians
- 28. CBO, unique index with BLEVEL <= 1: unfavorable nested loop joins
- 29. CBO, no system statistics: High costs for the sorting of few data records
- 30. CBO: Unfavorable merge join cartesians
- 31. CBO, OR operation with sub query: Unsuitable access path
- 32. CBO, histograms, bind variables: Unsuitable access paths
- 33. CBO, DBMS_STATS, histograms: The optimum index is not used if different column values are identical in the first 32 characters
- 34. CBO, N-Literals: The optimum index is not used
- 35. CBO, Oracle 9i, FIRST_ROWS(n)-Hint: Unfavorable full table scan or index fast full scan
- 36. CBO, Oracle 10g: Fully qualified index is not used
- 37. CBO, OPTIMIZER_INDEX_COST_ADJ < 100: Adequate index fast full scan is not used
- 38. CBO, histograms, date specifications: Inadequate join because of incorrect calculation of "Estimated Rows"
- 39. CBO, FIRST_ROWS(n), Oracle 10g: Fully qualified index is not used
- 40. CBO, range on join condition: An unsuitable join organization is used
- 41. CBO, Oracle 10g: Increased costs for IN LIST accesses
- 42. CBO, Oracle 10g: Incorrect index usage on internal tables of a semi-join
- 43. CBO, Oracle 9.2.0.7 / 9.2.0.8, 10.2.0.2, DBMS_STATS, Character columns with numerical content: Unfavorable accesses due to cardinalities that are calculated too low
- 44. CBO, Oracle 10.2.0.2: Cardinalities that are too low for histograms on join columns
- 45. CBO, Oracle 10.2.0.2: Optimal OR concatenation is not used
- 46. CBO: Unfavorable join sequence due to low cardinality
- 47. CBO: Correlated conditions
- 48. CBO, Oracle 10.2.0.2 or higher: Poor performance with many HASH GROUP BY for small datasets
- 49. CBO: Poor performance with DISTINCT/GROUP BY and restricted resulting set
- 50. CBO, DBMS_STATS: Unfavorable index accesses if only few records exist
- 51. CBO, Oracle 10g: Unfavorable nested loop joins with OPTIMIZER_INDEX_CACHING = 50
- 52. CBO, BI: No direct join of two dimensions only via bitmap indexes of the fact table
- 53. CBO, Oracle 10.2.0.4 or higher: The system ignores IN lists as part of an IN LIST ITERATOR.
- 54. CBO: The sequence when you join three or more tables is not optimal if two of the tables are linked using the same join column.
- 55. CBO: Selective NOT conditions are not analyzed optimally.
- 56. CBO, Oracle 10g 10.2.0.4 or higher: Histograms are not taken into account when using column group statistics.
- 57. CBO, Oracle 10g 10.2.0.4 or higher: Column group statistics are not taken into account for IN lists.
- 58. CBO, Oracle 10g or higher: Index Unique Scan is now preferred, despite higher costs.
- 1. The RBO does not analyze an index column under the following conditions:
- The column is not in item 1 or 2 of the index.
- Not all columns of the index are specified, or an index column is specified with a range condition.
- The conditions on the column are specified with an IN list or OR operation.
This response is also called the "Third Column Blues". If the first two index columns are not particularly selective, high runtimes may occur, despite the optimum index being used.
To avoid the problem, specify the index column in question with "=" if possible. Alternatively, you can change from the RBO to the CBO (for example, by creating statistics).
This response, which at first does not seem to make sense, is logical in that you can avoid a high number of OR concatenations in the execution plan if numerous conditions include IN lists. For more information, also see Note 869006.
- 2. If OR and at least one LIKE is used to access the second index column in the WHERE condition (for example, "... ("VARKEY" = :A1 OR "VARKEY" LIKE :A2) ..."), this index column is not used to gain access.
One solution is to make changes to the WHERE condition: Either avoid combinations of OR and LIKE or ensure that the field in question is the first field in the index.
Alternatively, creating statistics and the subsequent use of the CBO will solve the problem. To avoid statistics being deleted by BRCONNECT again, make an ACTIV=A entry for the relevant table in DBSTATC (see also Note 106047).
- 3. When deciding on an access path, the RBO follows its predefined rules. In particular, rule 10 ("Bounded Range Search on Indexed Columns") frequently applies in the SAP environment, for example when several indexes specify the same number of key fields with "=". Since the RBO does not recognize any access costs, all of these indexes are considered to be equivalent. Internal criteria (for example, the order of the entries in the row cache) will determine which index is actually used. This therefore cannot be influenced easily.
Check whether it is possible to use the CBO instead of the RBO without serious side effects.
Alternatively, you can create the optimum index, since the RBO gives priority to new indexes over existing indexes.
- 4. If you see costs greater than 0 in the Explain plan, you know that CBO is being used. With R/3 Releases up to and including 3.1I, no cost information is given in the Explain in Transactions such as ST04 and ST05. Therefore, it is not immediately apparent whether CBO or RBO is being used. An Explain at Oracle level, for example, provides a solution.
If an SQL statement is supposed to use the RBO (for example, R/3 <= 3.1I, pool and cluster tables, other tables with special handling according to Note 122817, specification of a RULE hint) but the CBO is used, this would be for one of the following reasons:
- The parameter OPTIMIZER_MODE is set to CHOOSE and there are statistics for at least one object contained in the SQL statement. In this case, a RULE hint can enforce the use of the RBO. If the object incorrectly contains statistics, the RBO can also be activated by deleting the statistics.
- A hint (FULL, INDEX, FIRST_ROWS, USE_CONCAT, ...) is being used. The RBO can only be used if no hint is specified.
Since newer QRFC supplements work with a FIRST_ROWS hint when accessing TRFCQIN and TRFCQOUT, unlike before, statistics must be generated for these tables to avoid performance problems (see Note 742950).
- The parallel DEGREE or the parallel INSTANCES are greater than 1 for at least one table involved in the SQL statement:
SELECT DEGREE, INSTANCES FROM DBA_TABLES
WHERE TABLE_NAME = '';Normally, SAP does not deliver objects with values > 1 (see Note 651060). If there is no need for the values > 1, they can be reset to 1:
ALTER TABLE- The system always uses the CBO when accessing Index Organized Tables (IOTs, see Note 641435).
- The system always uses the CBO when accessing partitioned objects (Note 722188).
- Other features that are unknown to RBO (for example, "SAMPLE" statement) also lead to the activation of the CBO.
- As of Oracle 10g, the parameter OPTIMIZER_MODE is set to ALL_ROWS by default. If there are no statistics, this causes dynamic sampling to be used, in which statistics are generated "on the fly" on the basis of a small sample and then the CBO is used. For this reason, the CBO is used in Oracle 10g even though there are no statistics.
- 5. If you specify indexed columns with LIKE, >, <, >=, <=, or BETWEEN, the system can no longer use the columns that follow to restrict the index range scan. This also applies when you use bind variables and specify a LIKE value without a placeholder (in such a way that LIKE could actually be equated with "="); this is because the CBO does not know the contents of the bind variables when parsing takes place.
The CBO also has this "design flaw", in that it only includes the subsequent columns in the cost calculation under certain conditions (see FF1 / FF2 from Note 750631).
Note also that a LIKE on a number field does not allow the field to be analyzed effectively. This means that it must be scanned completely in each case, which is why the CBO does not take into account that the LIKE field will reduce costs.
None of the above restrictions are limitations in the CBO - during the cost calculation process, the CBO only follows the restrictions of the Oracle database system itself. Possible approaches to solving the problem include:
- If the column in the range in question only has a few static distinct values, the range can be replaced by an IN list. If you use IN lists, subsequent conditions can be analyzed without any problems occurring.
- Alternatively, you can use an index in which the unselective range column(s) is/are only specified at the end.
- To simplify, the SAP system globally uses a range condition in some cases, even if no placeholder is used. In this case, parsing the statement using the actual values instead of using bind variables can solve the problem. Notes 1008433 and 1041983 enforce this for the input help (F4_GET_RESULT), which is often affected, using a hint.
- 6. The following factors can cause several index accesses to be valuated with optimum costs:
- OPTIMIZER_INDEX_COST_ADJ < 100
- Multiplication of the distinct values for the filter factor (Note 750631) regardless of the dependency of the column values.
The optimum costs are often 1, but depending on the statement, release and parameterization, can be higher (2, 3, 4, and so on).
If there are identical costs, in older releases (<= 9.2.0.5) Oracle often selects the index with the name that comes first alphabetically (in the ASCII alphabet). In 9.2.0.6, the system response often cannot be reproduced. As of 9.2.0.7, the decimal places are also taken into account during the calculation of costs.
To avoid rounding errors during the cost calculation process, check first if Event 10183 is set correctly in accordance with Note 128648.
If the problem occurs with Oracle <=9.2. 0.6, in a lot of cases it can be corrected by upgrading to a current 9i or 10g patch set.
With Oracle 9i (>=9.2.0. 7) you can set the event 38060, so that the filter factor is restricted by the distinct keys of the index, which may mean that the access to the less favorable index will be evaluated as being more costly so that the correct index is used (see Oracle bug 3566843):
event = '38060 trace name context forever, level 1'As of Oracle 10g, the response is corrected, even if this event is not used.
Otherwise, in the case of alphabetical preference, you can rename the optimum index that is not used so that it comes before the index that is used (in terms of the ASCII alphabet). In many, but not all cases, this causes the CBO to choose this index. If an SAP standard index has to be renamed, you can do so by using the index naming convention described in function module DD_INDEX_NAME, without SAP having to make any adjustments. For example, if the indexes AUSP~N1 and AUSP~N3 exist, the index AUSP~N1 is used if the costs are the same. If you want to use the other index instead, you can rename it AUSP______N3. This name is just as valid for SAP. At the same time, the underscore has a lower coding than the tilde, meaning that after the name change, Oracle chooses the index AUSP______N3.
Alternatively, you can also increase the costs of the wrongly used index by moderately reducing the distinct values for the index columns using DBMS_STATS.SET_COLUMN_STATS. These were used in the index that was used incorrectly, but not in the optimal index (Note 724545).
- 7. If a FIRST_ROWS hint is entered, Oracle ignores the optimal index if its first column is not specified with "=", and if another index exists at the same time whose first column is specified with "=". This happens because the FIRST_ROWS hint sometimes makes decisions based on rules. You can solve this problem by using the FIRST_ROWS(
) hint as described in Note 772497. SAP will also stop using the classic FIRST_ROWS hint in future. For more information, also see Note 978710. There is a workaround for this problem, whereby you define the index with MANDT as the first column, since as a rule MANDT is specified with "=".
- 8. Since the CBO only sees bind variables and does not know the actual values, it assumes an equal distribution of the distinct values (different values) in the table (for example, for a table with 1000 entries and two different key values 'A' and 'B' -> CBO assumes 500 'A' and 500 'B' entries). If the relevant key fields of the optimal index have only a few distinct values, the CBO assumes that a large number of the entries must be read and therefore calculates relatively high costs for this index and a large number of returned entries. As a result, the CBO chooses a non-optimal index, an index full scan instead of an index range scan or - in the case of views or joins - a sort merge join instead of a more effective nested loop join with the relevant table as the entry table.
However, it is often the case that the key values specified in the WHERE condition rarely appear in the table or do not appear at all and for this reason the index is actually quite selective. This is especially true for indicator columns that have either the value " " or "X", although the indicator "X" given in the WHERE condition rarely appears. For example:
- Table BDCPS, Column PROCESS
- Table LTBP, Column ELIKZ
- Table LTAP, Column PQUIT
In addition, there are often situations in which a table's column values are almost always initial but are queried with a concrete value in the WHERE condition. Even then, the condition is selective despite a low number of distinct values. For example:
- Table AFPO, Column PROJN
The first step should be to check whether the number of calculated distinct values is lower than the actual number due to inaccurate statistics. You can determine the number of distinct values that actually exist by using the following statement:
SELECT COUNT(DISTINCT()) FROM The following statement delivers the existing distinct values according to the statistics:
SELECT NUM_DISTINCT FROM DBA_TAB_COLUMNS
WHERE OWNER = '' AND TABLE_NAME = ' ' AND
COLUMN_NAME = ''; If the first statement returns a higher value than the second statement, you should create more precise statistics for test purposes. If you have up-to-date COMPUTE statistics, both statements should return exactly the same result. If the problem can be solved by more precise statistics, the precision with which statistics are created can be permanently fixed in the table DBSTATC (see Note 106047).
If both statements return the same result and the optimal index has still not been read, you should first consider adjusting the application (specifying a hint in the source code, changing the WHERE condition, changing the application logic). You can also use a SUBSTITUTE hint together with histograms, so that Oracle can better assess the selectivity of the conditions that are used (see Note 797629).
If this is not possible, you can make the index (and any nested loop joins based on it) technically more attractive by increasing the number of distinct values for the key fields in question (see Note 724545).
Increasing the distinct values also makes index range scans more attractive compared to index full scans.
- 9. For accessing an index key field, the CBO calculates costs that are proportional to the length of the OR operation in which the key field is specified in the WHERE condition. If a key field is specified in an OR operation, the probability of an index access lessens in relation to the length of the OR operation. The longer the OR operation, the more probable a full table scan or an access using another, non-optimal index.
In R/3, OR operations are usually generated together with the FOR ALL ENTRIES statement. You can control the maximum length of the OR operation using the R/3 parameter rsdb/max_blocking_factor. See Note 881083 for an ideal parameterization.
You cannot use FOR ALL ENTRIES for range specifications. You can only employ individual measure in ABAP to limit the number of OR operations. Note 408215, for example, describes how to avoid multiple OR operations on ONJNR ranges (BETWEEN) from COSP as part of cost extractors.
- 10. As of Kernel 6.10, FOR ALL ENTRIES statements are normally converted to IN lists (rsdb/prefer_in_itab_opt = 1). This leads to similar problems with long IN lists as was previously the case when using OR operations, since the CBO applies overly high costs for an index access using the field of the IN lists. See Note 881083 for an ideal parameterization.
If the statement in question is not triggered by FOR ALL ENTRIES, you could try to split up the IN list in the application, or to convert the SQL statement into a FOR ALL ENTRIES expression.
- 11. For joins that are accessed with "ROWNUM <", the CBO frequently chooses a sort merge join. In contrast to a nested loop join, a sort merge join only delivers the complete hit list once all data has been read, sorted and combined. To give preference to the more favorable nested loop join, you can activate the automatic generation of a FIRST_ROWS hint for "ROWNUM <" statements in accordance with Note 135048.
- 12. The CBO cannot resolve transitive fields if they are specified in the context of an OR operation (Note 305225). For example:
SELECT * FROM "CAUFV"
WHERE "MANDT"=:A0 AND "AUFPL"=:A1 OR
"MANDT"=:A2 AND "AUFPL"=:A3Join condition: AUFK-MANDT = AFKO-MANDT
View fields: MANDT = AUFK-MANDT
AUFPL = AFKO-AUFPLThe Optimizer cannot evaluate the transitivity for the MANDT since there is an OR condition in the SQL statement. This is why the SAP standard index AFKO~1 using MANDT and AUFPL cannot be used because the MANDT specified in the view is from the Table AUFK rather than the Table AFKO, and the system does not recognize that the AFKO-MANDT and AUFK-MANDT fields are the same.
If the transitive field is not selective (like MANDT in the above example), an additional index can be created without the field.
If this is a view that you have defined, check whether the transitive field can be taken from the table from which the most selective field of the WHERE condition comes.
If the OR operation is taken from a FOR ALL ENTRIES statement, you can set the parameter rsdb/max_blocking_factor to 1 as a workaround, since this does not generate any further OR operations. Since this greatly increases the number of remote SQL statements, you should only implement this workaround if all other approaches have failed and if the problem causes serious malfunctions.
- 13. When statistics are created with ANALYZE TABLE, only the first 32 characters of the entries are compared to determine the distinct values of table columns. In individual cases in the SAP environment, this can become problematic if columns with more than 32 characters are left-aligned and filled out with zeros. In this situation, a value that is far too low may be calculated for the distinct values of the column, which leads to higher costs being assigned to the optimal index that indexes this column.
See Note 365480 and use the DBMS_STATS to calculate statistics or manually increase the value for the column's distinct values (Note 724545).
- 14. If you use Oracle below 9.2.0.5 and if you create histograms in columns with only one distinct value, the selectivity of these columns is valued with 1/100 instead of 1 for bind variables. See Note 750631 and avoid using histograms with Oracle versions below 9.2.0.5. Another possible workaround is the manual increase of the distinct values from 1 to 2 (Note 724545).
- 15. Table entries that have a NULL value in ALL index columns are not included in the index. For this reason, Oracle MUST carry out a full table scan in certain cases to access these table entries and an index is not used (even if an explicit index hint is specified). This is the case if both the following conditions are simultaneously met:
- None of the indexed columns have set a NOT NULL constraint, in other words, the following query returns only "Y" (
, the indexed columns are capitalized):
SELECT COLUMN_NAME, NULLABLE FROM DBA_TAB_COLUMNS
WHERE TABLE_NAME = '
COLUMN_NAME IN ('', ' ', ..., ' '); - Due to the existing conditions, all index columns can simultaneously contain the value NULL.
In the SAP environment, NOT NULL CONSTRAINTs are usually used (see Note 617679). However, if columns are attached to tables without the "Initial Value" field being set, the DDIC usually forgoes the NOT NULL CONSTRAINT and NULL values occur. To solve the problem, check if a NOT NULL CONSTRAINT can be activated (Note 617679), and if you need to specify "IS NULL" or "IS NOT NULL" in the SQL statement. As an alternative, you can add a "NOT NULL" column to the index to allow Oracle to use the index.
- 16. As of Oracle 9.2.0.4, when you use the FIRST_ROWS hint in connection with an ORDER BY, preference is given to the indexes that have the same order as the ORDER BY and that therefore do not make it necessary to sort the resulting quantity. This can mean that indexes that are significantly more practical cannot be used, since they do not index the ORDER BY fields. Setting the following parameter solves the problem:
_SORT_ELIMINATION_COST_RATIO = 10This means that more practical indexes that do not support the ORDER BY are taken into account if the calculated costs are at least 10 times better than the index that supports the ORDER BY.
Alternatively, you can also avoid the problem by using the FIRST_ROWS(
) hint. - 17. Up to Oracle 9.2.0.5, if a field that has two distinct values is accessed using BETWEEN, Oracle uses 2/# table entries as the filter factor (see Note 750631). If a table contains a large number of lines, the indexes that contain this field are unjustly evaluated more favorably and are therefore used more often by the system.
In addition to an upgrade to Oracle >= 9. 2.0.6 , you can also avoid the problem by setting the number of distinct values for this field to a value other than two (one or three for example) in accordance with Note 724545.
- 18. In the following circumstances, the CBO does not use an index in spite of lower costs:
- The first column of the index is specified with a range condition (LIKE, >,<, >=, <=, BETWEEN).
- A column of another index is specified with "=" or IN, which is either the first index column or can be easily accessed by using an index skip scan.
- The access costs for this other index are lower than for a full table scan.
The reason behind this rule-based decision is that a range condition is interpreted by the CBO as a "guess" that is seen as unfavorable regardless of the calculated costs.
As of Oracle 9.2.0.7, you can deactivate this rule-based mechanism by using the following event:
event = '38068 trace name context forever, level 100'You can use the level to specify the percentage of guess costs relative to the costs of the best non-guess access up to which the system should continue to use the guess-access. If you enter 100 (percent), you specify that the system should always use the access that has the lowest cost, and that the guess indicator should be ignored.
Other workarounds are:
- At the beginning of the index, enter an additional column that is specified in the WHERE condition with "=" or IN. In many cases, you can use the column MANDT. Make sure that ALL statements that use this index also specify the additional column. If they do not, the performance may deteriorate in other statements.
- Reduce the costs of a full table scan so that the full table scan is more favorable than the access through the unfavorable index currently in use. You can do this by reducing NUMBKLS as described in Note 724545, for example. However, you must make sure that this change does not have any negative effect on other accesses.
- 19. For statements with AND EXISTS and OR operations and at least one range on a column to be joined, Oracle 9i does not use an index range scan. To solve this problem, you must set the Oracle parameter
_ALWAYS_SEMI_JOIN = OFFSee also Note 841280.
- 20. The system does not execute an optimal access via index skip scan, although the CBO calculates optimal costs for the skip scan (use the INDEX_SS hint to check). This is caused by an Oracle bug (4050226) that has been repaired as of 9.2.0.7.
- 21. If a SELECT with nested OR concatenations does not use the best access path on Oracle 9i (<= 9.2.0.6) and instead executes a Full Table Scan, an Index Full Scan or another unsuitable access, Oracle bug 4157426 may be present. This has been resolved as of Oracle 9.2.0.7 and 10.1.0.5. To activate the fix, you must set the following parameter:
_OPTIMIZER_OR_EXPANSION = DEPTHAs of Oracle 10. 2 _OPTIMIZER_OR_EXPANSION is set to DEPTH by default, and so you need not set it explicitly.
A possible temporary workaround is to use the USE_CONCAT hint. For more information, see Note 849229.
- 22. When using bind variables, Oracle does not allow an index skip scan using columns that are specified with ranges (BETWEEN, LIKE, >, <, >=, <=). Possible workarounds are:
- Create an index that contains the range column at the end (or not at all).
- Use an IN list instead of an interval.
- Oracle >= 9.2.0.8, 10.2.0.2: Use an INDEX_SS hint.
- 23. When using histograms and concrete values, the wrong estimated costs and estimated rows are determined if the start or the end of a range condition matches the endpoint value of a histogram bucket. For example, the minimum value for the estimated rows is always #TableRows / #HistogramBuckets, regardless of the size of the BETWEEN interval. Determine the critical endpoint values as follows:
SELECT ENDPOINT_ACTUAL_VALUE FROM DBA_TAB_HISTOGRAMS
WHERE TABLE_NAME = ''; This problem is fixed as of 9.2.0.7. There are bug fixes for 9.2.0.6 (Note 880568).
The only other way of solving this problem is to use another number of histogram buckets, so that the BETWEEN area no longer begins with an endpoint value. The standard is 75 buckets, so that for example 76 buckets would be suitable. These can be created as follows:
ANALYZE TABLEESTIMATE STATISTICS SAMPLE
PERCENT FOR COLUMNSSIZE 76; - 24. If several range conditions are specified on an index column, they are often used insufficiently for the index access. Therefore the statement
SELECT ... WHERE XXX > '10000' AND XXX > '99999';results in an index access with the followingpredicates:
1 - access("XXX">'10000')
filter("XXX">'99999')Firstly, all index entries that are larger than 10000 are read according to the ACCESS predicate. It is only after this has been done that the results set is reduced to the entries that are larger than 99999. It would make more sense for the index access to use only the area XXX > 99999 right from the start.
Possible workarounds to avoid this response are:
- Redesigning the ABAP source code, avoiding redundant conditions (such as XXX > 10000 in the above example)
- Using BETWEEN instead of the characters ">" and "<"
- Using the NO_EXPAND hint if a range is specified with NOT BETWEEN.
- 25. Due to the fix for Oracle bug 3672985, even "=" conditions are largely analyzed as of 9.2.0.7 if Bind Value Peeking is active. If the specified value lies outside the interval of Low Value and High Value for the column, a high selectivity is adopted, even if the column only has a small number of attributes.
Due to a bug that occurs when CHAR (SAP data type) is converted into VARCHAR2 (Oracle data type), certain conditions are evaluated as being very selective (which is incorrect), which gives optimal costs to very unsuitable indexes (Oracle bug 4752814).
For example, if the system contains only client 100 and you execute a query with "WHERE MANDT = '100'", the CBO assumes that NO data record matches the condition, while in fact ALL data records would match it.
As a result, an SAP system in which Bind Value Peeking is active on Oracle 9.2.0.7 and 10.2.0.2 may be almost unusable in many cases.
The general SAP recommendation for solving this problem is that you set the following parameter in order to deactivate Bind Value Peeking:
_OPTIM_PEEK_USER_BINDS = FALSEThe bug has been corrected in 9.2.0. 8 and 10.2.0.4.
- 26. In Oracle 9i, the estimated rows in joins may be incorrect. In addition to this, exchanging join conditions (which is actually not relevant to the process of calculating costs and rows) may lead to severe differences as regards the estimated rows. This can lead to very unfavorable accesses in joins of three or more tables. As of Oracle 9.2.0.4, you can avoid the problem by setting the following parameter:
_OPTIMIZER_JOIN_SEL_SANITY_CHECK = TRUEIn Oracle 10g, the parameter is set to TRUE by default.
- 27. When you create estimated histogram statistics using DBMS_STATS, the statistics values NUM_DISTINCT, LOW_VALUE and HIGH_VALUE may not be set correctly. As a result, the estimated rows value may be noticeably smaller than it should be. This can result in incorrect join operations such as MERGE JOIN CARTESIAN in the case of multiple joins. This bug has been fixed as of Oracle 9.2.0.6 (see Note 753096).
- 28. If, according to statistics, an index has a BLEVEL of 0 or 1, an index unique scan (without a subsequent table access) is valued with costs of 0. As a result of this, joining an index of this kind via nested loop is valued with costs of 0, even if a very large number of data records is expected from the external table. For example:
SELECT STATEMENT ( Estimated Costs = 1,202 , Estimated #Rows = 2,102 )
7 NESTED LOOPS
( Estim. Costs = 1,202 , Estim. #Rows = 2,102 )
5 HASH JOIN
( Estim. Costs = 1,202 , Estim. #Rows = 88,083,730 )
...
6 INDEX UNIQUE SCAN /SAPAPO/MATKEY~0
Search Columns: 2Here, the CBO estimates that it must access 88.083.730 on the index /SAPAPO/MATKEY~0, but calculates costs of 0 for it. You can tell this is the case because, in the nested loop row, the same costs are specified as are specified in the hash join row (1.202), and no "Estim. Costs" are displayed for the index unique scan.
To correct this problem, increase the BLEVEL to 2 as described in Note 724545.
Other solutions include using system statistics (Note 927295) or setting OPTIMIZER_INDEX_CACHING to 1. Both measures may affect other SQL statements, so they should only be implemented in production environments after thorough testing.
As of Oracle 10g, system statistics are used as standard, which is why the observed problems should not occur anymore.
- 29. If no system statistics are used, the CBO calculates unjustifiably high costs for the sorting of few data records. The problem is aggravated when the size of SORT_AREA_SIZE or PGA_AGGREGATE_TARGET is increased, even though increasing the size of this parameter should actually reduce costs. Therefore, if the value of SORT_AREA_SIZE or PGA_AGGREGATE_TARGET of the CBO is high, costs of 54 are determined for the sorting of a single data record.
As a result of this behavior, excessive preference is given to indexes that support the ORDER BY columns, since no sorting is required in this case.
You can solve the problem by creating system statistics (Note 927295). Reducing the size of SORT_AREA_SIZE or PGA_AGGREGATE_TARGET can positively influence the CBO decision. However, this parameter should not be set to lower that the SAP standard recommendations.
As of Oracle 10g, system statistics are used as standard, which is why the observed problems should not occur anymore.
- 30. For various reasons, the CBO can decide to use a cartesian merge join. In the SAP environment, this type of access is often associated with impairing performance and is hardly ever of benefit. As of Oracle 9.2.0.6, this type of access can be completely deactivated with the following event (see Note 960633):
event = '38043 trace name context forever, level 1'However, as of Oracle 10g, you must set the following parameter:
_OPTIMIZER_MJC_ENABLED = FALSE- 31. Due to a design limitation, the CBO cannot correctly evaluate OR operations with sub queries (see Notes 951416 and 1116930). The example of the following SQL statement that was previously used with R3SZCHK illustrates this:
SELECT
NVL(BYTES,-1) FROM USER_SEGMENTS
WHERE SEGMENT_NAME = 'ATAB'
OR SEGMENT_NAME IN
(SELECT SEGMENT_NAME FROM USER_LOBS WHERE TABLE_NAME = 'ATAB');A concatenation of a USER_SEGMENT-access and a USER_LOBS/USER_SEGMENTS-join would be possible. Instead, the CBO decides on the following access:
SELECT STATEMENT
4 SORT AGGREGATE
3 FILTER
1 TABLE ACCESS FULL TEMP_USEG
2 INDEX RANGE SCAN TEMP_ULOBS_1As a result, an index range scan is carried out on TEMP_ULOBS_1 for every entry from TEMP_USEG, which can lead to a very high number of block accesses.
In this specific case, you can use Note 1047369 to solve the problem.
We recommend that you avoid OR operations in connection with sub queries. Instead, you should divide the statement into several smaller statement or use UNIONs.
- 32. Despite the solving of the histogram problems described under point 14 and 17, side effects with histograms on SQL statements that work with bind variables may still occur with more recent Oracle versions. This is caused by the fact that, during the creation of histograms, DENSITY values can be calculated that deviate from 1 / NUM_DISTINCT. In addition, the filter factors are calculated by multiplying it with DENSITY instead of dividing it by NUM_DISTINCT within the cost calculation (Note 750631), which will have a significant effect on the calculated cost. A technical solution is currently avoiding the use of histograms (if possible). Otherwise you can specify a suitable hint or adjust the CBO statistics in accordance with Note 724545.
- 33. If you use DBMS_STATS to create statistics with histograms, the system evaluates only the first 32 characters when determining the distinct value. This problem can be compared to the ANALYZE problem (point 13). A solution is to avoid histogram statistics or manually edit the distinct values in accordance with Note 724545.
With Oracle Version 11g or higher and with DBMS_STATS auto sample size being used at the same time, the system determines the distinct values correctly. However, the histogram information continues to take into account only the first 32 characters. The auto sample size can be activated with the BRCONNECT parameter "-m A" (Note 892296).
- 34. If conditions with national character set literals are rejected (you can recognize this from the "N" at the beginning, for example, WHERE MSG_ID=N'4b34a370-17d7-11db-a301-e8330ac889e2'), even though the relevant table columns have the type VARCHAR2, then Oracle cannot use the condition for index access. In such a case, either use the NVARCHAR2 data type, or do not use any N literals.
- 35. As of Oracle 9i, if you use the FIRST_ROWS(n) hint, the system may execute unfavorable accesses using full table scan or index fast full scan (Oracle bug 3521347). In such a case, do not use the FIRST_ROWS(n) hint. See Note 1004794.
- 36. As of Oracle 10g, the index distinct keys are also included in the cost calculation. However, this only applies in cases where all index columns are entered in the WHERE clause. As a result of the index distinct keys often being significantly lower than the product of the distinct values of the columns, a fully qualified index may be valued as being worse than other indexes. This error response (Bug 5705257) is corrected by Optimizer Merge Fix 5882450 (Note 981875) or merge fixes that were built on it.
Bear in mind that the bug fix corrects the disadvantage of fully qualified index accesses only. The distinct keys are still used for restricting the selectivity requirement. Therefore, index accesses may still be evaluated as being more costly compared to Oracle 9i.
- 37. By default, when you set OPTIMIZER_INDEX_COST_ADJ to < 100, this has no effect on the cost calculation for index fast full scans. Due to OPTIMIZER_INDEX_COST_ADJ, an inadequate access may therefore be valued as being better than the optimal fast full scan. As of Oracle 9.2.0.8 (including the merge fix from Note 992261) and 10.2.0.3, you can set event 38085 to correct this behavior:
event = '38085 trace name context forever, level 1'- 38. In Oracle, the system often saves date columns in the VARCHAR2 columns. As a result, Oracle may not recognize that certain values (for example, 55.66.2006) are invalid. If you now create histograms on one of these columns and use a range condition to access it, the system may estimate an incorrect cardinality in the case of a year change. For example:
- WHERE condition: BETWEEN '20070101' AND '20070105' (-> 4 days)
- Bucket: 20061228 - 20070105 (-> 8 days)
Assuming that these are date specifications, you could expect 50% of the entries of the histogram bucket back (4days/8 days). On the other hand, Oracle interprets values as normal strings and calculates:
(20070105 - 20070101) / (20070105 - 20061228) =
4 / 8877 = 0.045 %Due to the cardinality being significantly too low, then for no reason, the relevant tables may be used to access joins.
Possible solutions include:
- Creating statistics without histograms (in which there may be disadvantages in other areas)
- Using a higher number of histogram bucket ("-b" option to create BRCONNECT statistics)
- Using a date data type in Oracle (if the application allows this)
- 39. Due to Oracle bug 5694984, Oracle 10.2 determines ALL_ROWS costs for indexes, whose columns are all entered with "=" conditions, even if you have entered a FIRST_ROWS(n) hint. The resulting higher costs may lead to such an index not being used. This is incorrect. Oracle Bug 6350462 may cause similar problems.
Import at least CBO merge fix from Note 981875 to correct the problem.
- 40. The CBO accepts a selectivity of 5% by default for range specifications within join conditions (for example, "T_00.LFT < T_01.RGT"). This is obviously too low in many cases, and tends to result in the tables in question being joined too early in complex multiple joins. Therefore, avoid using ranges in join conditions if possible.
- 41. As of Oracle 10g, IN LIST ITERATION costs of at least one are accepted for each element. This can lead to selective indexes with IN LIST columns being valuated as significantly more expensive than with Oracle 9i, even if OPTIMIZER_INDEX_CACHING is set significantly higher. Possible approaches include:
- Do not include the IN LIST column in the index (if acceptable from a selectivity view).
- Use BETWEEN instead of an IN list (if meaningfully feasible).
- Shorten the IN list (for example, by ensuring that the blocking factors are not set too high in accordance with Note 881083 for FOR ALL ENTRIES expressions).
- 42. Due to bug 5680702, the system assesses very low costs for unsuitable indexes on internal tables of semi-joins (as they are used in the context "AND EXISTS", for example), and this can greatly increase runtimes. Until a fix is available for this bug, you can only correct this behavior by adjusting the statistics as described in Note 724545 (for example, by raising the BLEVEL of the bad index).
- 43. If you create DBMS_STATS statistics and character columns contain purely numerical values that are more than six characters long, the system may exhibit unfavorable accesses for Oracle versions 9.2.0.7, 9.2.0.8 and 10.2.0.2 (Oracle bug 5284303). In this case, the system may accept cardinalities that are far too low. Refer to note 948197 for more information.
- 44. With Oracle 10.2.0.2, histograms on joined columns can lead to the CBO calculating too low cardinalities and, as a result, using unfavorable join chains with complex accesses (for example, in the SAP Business Information Warehouse environment) (bugs 5766310 and 6051211 ). You can correct this action by creating statistics without histograms. The optimizer merge fix 6321245 (or higher) also corrects the problem.
- 45. For join and view accesses in connection with Oracle 10.2.0.2, the system may ignore an optimal OR concatenation and use an unfavorable access, which is often related to high costs. By specifying an USE_CONCAT hint, the optimal access with lower costs is used.
This problem may be caused by Oracle bug 5129407 and can be fixed with the current optimizer merge fix as described in Note 981875.
It may also be triggered by bug 5705630. As a workaround, you can set the following event:
event = '10168 trace name context forever, level 1'If this event is successful, you can, instead, import the current CBO merge fix in accordance with Note 981875 and use the following parameters to activate the bug fix 5705630:
_FIX_CONTROL = '5705630:ON'If the problem occurs in connection with a FOR ALL ENTRIES expression in systems with Release 4.6C or lower, the following SAP parameters may solve the problem in many cases because it converts the expression into an IN list display (Note 881083):
rsdb/prefer_in_itab_opt = 1
rsdb/max_in_blocking_factor = 5As of Kernel 6. 20, these values are standard values. They are also a reasonable parameterization for Kernel 4.6x.
- 46. As of Oracle 9i, a new method for calculating the cardinality of joins is active. Due to this method, the lowest cardinality possible may no longer go towards 1 but towards 0. This reduced cardinality requirement may lead to serious incorrect CBO estimations and unfavorable join sequences with low performance. For multiple joins that run for a considerable time, make sure that the "Estimated Rows" for the join are frequently 1 (internally, the actual values may be lower than one, but the system always displays 1). Check whether deactivating the new cardinality calculation solves the problem:
_OPTIMIZER_NEW_JOIN_CARD_COMPUTATION = FALSE- 47. The CBO usually assumes that stochastically independent column values are used. However, correlated, in other words, conditions that depend on each other, are often specified in the WHERE clause, for example:
"DT"."SID_0CALDAY" BETWEEN 20070301 AND 20070430 AND
"DT"."SID_0CALMONTH" BETWEEN 200703 AND 200704In this case, the CBO assumes that only approximately 2/12 * 2/12 of all entries from 2007 correspond to the conditions because both the day condition and the month condition restrict to 2 of the 12 existing months. However, actually approximately 2/12 of all entries correspond to the conditions because the month condition does not further restrict the resulting set.
Therefore, the cardinality that is expected by the CBO is often lower than the actual cardinality. To solve the problem, you can use the regular workarounds (such as hints or statistics value adjustment) or proceed as follows:
- If an index is created using critical columns, the CBO as of Oracle 9.2.0.7 can use its DISTINCT_KEYS statistics value to determine the actual correlation of the columns (event 38060 must be set as described above).
- With Oracle 10.2.0.2, the DISTINCT_KEYS are integrated into the CBO considerations to a certain extent by default. However, these are not consistently taken into account.
- As of Oracle 10.2.0.4, we recommend that you use an increased dynamic sampling level for OLAP systems (Note 830576, OPTIMIZER_DYNAMIC_SAMPLING = 6). This results in a good estimate of the correlation of several columns in most cases. In OLTP systems, this setting is not suitable because bind variables are usually used (this deactivates dynamic sampling) or a high parsing load is created in individual cases.
- In addition, as of Oracle 10.2.0.4, a simplified version of column group statistics (Oracle 11g feature) is available that results in a consistent consideration of distinct keys of indexes. For this, you must set _FIX_CONTROL = '5765456:3'. As of 10.2.0.4, this is an SAP standard recommendation (Note 830576).
If correlation problems occur, we recommend to upgrade to Oracle 10.2.0.4 or higher.
- 48. As of Oracle 10g, as an alternative for SORT GROUP BY, a HASH GROUP BY is also available for the aggregation. While HASH GROUP BY has considerable advantages with regard to performance when grouping large datasets, SORT GROUP BY is more suitable for smaller datasets. However, due to bug 6399597, the CBO also uses a HASH GROUP BY for small expected datasets. This may lead to a considerable deterioration in performance if the aggregation is executed frequently. This may be the case, for example, if a subquery (Note 1116930) is resolved based on a FILTER and if it contains an aggregate function. This problem can be solved as follows:
- Implement Bugfix 6399597 and set the following parameters to activate the fix:
"_FIX_CONTROL"='6399597:ON'
- If you cannot implement Bugfix 6399597 at this time, as a workaround, you can set the following parameter:
_GBY_HASH_AGGREGATION_ENABLED = FALSE
Note that these are very specific exceptional cases and that HASH GROUP BY does not lead to a measurable deterioration in performance even for small datasets if you execute it once.
- 49. In the SAP environment, if you use DISTINCT or GROUP BY to perform a query, Oracle always processes the complete dataset, even if (for example, due to "ROWNUM <=") only a small resulting set is required (see, for example, Oracle bug entry 7443961). This problem occurs because DISTINCT/GROUP BY must always be performed first for the currency of the logical consistency before the resulting set is limited. The system therefore uses the following nested query:
SELECT ... FROM
(SELECT DISTINCT ... FROM ...)
WHERE ROWNUM <=; You can solve this problem only by omitting DISTINCT or GROUP BY or by limiting to the smallest possible total dataset (if possible).
- 50. If a table contains only a few or no entries (temporarily or permanently), this may cause effects that are not required when you use DBMS_STATS to create statistics. DBMS_STATS counts only the reserved index leaf blocks, which may cause the value for LEAF_BLOCKS to be low (for example, after you delete a large amount of data). If the table is completely blank, the value for LEAF_BLOCKS is 0 (which is impossible because at least one leaf block always exists). Actual index accesses must also read unused leaf blocks. As a result, the actual effort that is required to access the index is significantly higher than CBO estimated based on the leaf blocks. In the worst case scenario, situations may occur in which the CBO decides to perform multiple full index scans or a fast full index scan inside a nested loop join because the system values the costs as 0 due to LEAF_BLOCKS being equal to 0.
This problem is described in Oracle Bug 5099019, for which a fix exists as of Oracle 10.2.0.4 (see Note 1165319). To activate this, you must also set the following parameter:
_FIX_CONTROL = '5099019:ON'Alternative workarounds are:
- Use hints
- Avoid creating statistics at times when a fluctuating table is not very full.
- Adjust LEAF_BLOCKS manually in accordance with Note 724545.
- 51. In OLTP environments with Oracle 10g, we recommended that you set OPTIMIZER_INDEX_CACHING = 50. In individual cases, this may result in unfavorable nested loop joins being used if the inner part of the join can be performed using a pure index access, since this may be valuated with costs close to zero. As of the end of 2008, we therefore recommend that you use the Oracle default value 0 in OLTP environemnts as well (refer to Note 830576 for further information).
- 52. Under certain circumstances (for example, within the F4 search help), several dimensions must be joined together in BI, without data from the fact table being queried. In such situations, it would be useful if the dimensions could be linked to each other directly via the bitmaps of the relevant bitmap indexes of the fact table. This is not the case, however, since Oracle cannot map bitmap entries to index key fields (mapping is always performed in the other direction). Due to this restriction, you must either access the fact table or you must perform a ROWID-based index join.
- 53. Up to Oracle 10.2.0.2, the system always processed IN lists in the relevant columns in the form of an IN LIST ITERATOR even if capacity required for the IN list was significantly higher than the selectivity gain. As of 10.2.0.4, the CBO determines costs both for the IN list iteration and the evaluation of the condition as part of an index filter; it then selects the access that has the lowest costs. In individual cases, the system may no longer use an IN list that was reduced by the resulting set to restrict an index range scan and filters these only in retrospect. You can recognize this situation as follows:
- The number of buffer gets for the access is inexplicably high.
- The restriction with the IN list is not part of ACCESS_PREDICATES in V$SQL_PLAN.
- The SEARCH_COLUMNS are smaller than expected.
- The system may not display an IN LIST ITERATOR in the access plan.
In general, this behavior is required. By deactivating fix 4600710 ("_FIX_CONTROL"='4600710:OFF'), you could deactivate the feature, but this is generally not useful. Instead, you must check why the CBO decides incorrectly. Depending on the situation, you can take such measures as SUBSTITUTE hint with histograms or the rededuction of the distinct values of the leading index columns. A further alternative is the NUM_INDEX_KEYS hint that you can use to specify the number of IN lists to be evaluated (where you can use one IN list as a filter predicate at the most):
NUM_INDEX_KEYS("" " " ) - 54. When you join more than two tables using the same join column, the CBO may no longer be able to evaluate transitivity correctly. For example:
SELECT * FROM
"VBAK" T_00 INNER JOIN
"VBAP" T_01 ON
T_01 . "MANDT" = :A0 AND
T_00 . "VBELN" = T_01 . "VBELN" INNER JOIN
"VBEP" T_02 ON
T_02 . "MANDT" = :A1 AND
T_02 . "POSNR" = T_01 . "POSNR" AND
T_02 . "VBELN" = T_00 . "VBELN"
WHERE ...In this case, all three tables are linked by VBELN; however, the CBO does not recognize that T_01 . "VBELN" = T_02 . "VBELN" applies. If these cause poor performance, you must adjust the join conditions in the ABAP source code accordingly.
For more information, see the relevant section in Note 305225.
- 55. In the case of a NOT specification, the CBO first attempts to avoid the NOT as described in Note 750631 (for example, "NOT <=" -> ">"). This is also possible for "=" and "IN" conditions (for example, "NOT =" -> "<" OR ">"); however, CBO does not consider this. For selective NOT conditions on indexed columns, this causes an unnecessary overhead because no restriction takes place for the index range scan. In this case, you should remove the NOT from the query if possible and the system should access positive ranges or positive value lists instead.
In the case of IS NOT NULL, this is more difficult because conditions such as "> NULL" or "< NULL" are not permitted. Here, the system can (if possible) access only positive value lists or it can check whether you can use a NOT NULL constraint to deactivate NULL values on the column (if necessary, in conjunction with converting the NULL values to SAP default values).
- 56. If you use the simplified column group statistics on Oracle 10g (10.2.0.4 or higher) (_FIX_CONTROL = 5765456:3 is set) and if fix 6972291 is also activated (_FIX_CONTROL = 6972291:ON), the existing histogram statistics are ignored. In individual cases, this may lead to unfavorable CBO decisions because the CBO can no longer identify whcih values occur frequently and which values occur less frequently. This problematic side-effect is described as part of Oracle bug 8725958. If problems occur, as a test, you can remove _FIX_CONTROL 6972291 or set it to OFF.
- 57. The simplified column group statistics are ignored on Oracle 10g if one of the relevant columns is specified with an IN list instead of with an "="condition. This may cause Oracle to evaluate IN lists relatively favorably and the estimated rows may be less when specifying an IN list than when specifying a single value. This is Oracle bug 9081848 that is fixed with 11g. However, there will be no fix for Oracle 10g. The fix with Oracle 11g may cause IN lists to be evaluated as being more costly and therefore, the CBO may tend to perform less accesses using INLIST ITERATOR.
- 58. If bug fix 6430500 is activated (_FIX_CONTROL = '6430500:ON'), the INDEX UNIQUE SCAN accesses are preferred, regardless of the calculated costs. This rule-based behavior makes sense in singles roles, but it can also lead to undesired effects. Therefore, INDEX UNIQUE SCAN is preferred if there is another index that would enable an index-only access (enabling you to avoid the (often expensive) table access). In this case, you can (if required and contrary to the SAP default recommendation) delete the parameter _FIX_CONTROL = '6430500:ON' so that the purely cost-based index selection is used.
Header Data
Release Status: Released for Customer Released on: 14.10.2011 13:09:27 Master Language: German Priority: Recommendations/additional info Category: Performance Primary Component: BC-DB-ORA Oracle Secondary Components: SV-BO-DB-ORA Oracle Performance Problems
No comments:
Post a Comment