 |
|
Oracle 10g de-supports rule-based SQL Optimizer
Oracle Tips by Burleson Consulting
|
With a large number of Oracle shops
using the rule-based optimizer (RBO), migration to cost-based
optimization (CBO) will become a important task when migrating to
Oracle10i, where the RBO will disappear.
As you may know, Oracle provides several
parameters that can adjust the behavior of the CBO to make it more like
rule-based optimization:
Today we examine optimizer_index_caching, and
we will cover the other parameters in later tips.
Important Note: Prior to Oracle 10g, adjusting these optimizer parameters
was the only way to compensate for sample size issues with dbms_stats.
As of 10g, the use of dbms_stats.gather_system_stats and improved
sampling within dbms_stats had made adjustments to these parameters far
less important. Ceteris Parabus, always adjust CBO statistics before adjusting
optimizer parms. For more details on optimizer parameters, see my latest book "Oracle
Tuning: The Definitive Reference".
optimizer_index_cost_adj
This is the most important parameter of
all, and the default setting of 100 is incorrect for most Oracle
systems. For some OLTP systems, re-setting this parameter to a
smaller value (between 10- to 30) may result in huge performance
gains!
If you are having
slow performance because the CBO first_rows optimizer mode is
favoring too many full-table scans, you can reduce the value of the
optimizer_index_cost_adj parameter to immediately tune all of the
SQL in your database to favor index scans over full-table scans.
This is sometimes a “silver bullet” that can improve the performance
of an entire database in cases where the database is OLTP and you
have verified that the full-table scan costing is too low.
Even in Oracle9i, the CBO sometimes
falsely determines that the cost of full-table scan is less than the
cost of an index access. The optimizer_index_cost_adj parameter
is a great approach to whole-system SQL tuning, but you will need to
evaluate the overall effect by slowly resetting the value down from
100 and observing the percentage of full-tale scans. You can also
slowly bump down the value of optimizer_index_cost_adj when you
bounce the database and then either use the access.sql or
plan9i.sql scripts or reexamine SQL from the STATSPACK
stats$sql_summary table to see the net effect of index scans on
the whole database.
The plan9i.sql
script (see code depot from book below) uses the v$sql_plan
view and a quickly the reduction in sub-optimal, large-table
full-table scans:
http://www.rampant-books.com/book_2005_1_awr_proactive_tuning.htm
Full table scans and counts
Note that "K"
indicates in the table is in the KEEP pool.
OWNER NAME
NUM_ROWS C K BLOCKS NBR_FTS
-------------- ------------------------ --------- - -
-------- --------
SYS
DUAL
N 2
97,237
SYSTEM
SQLPLUS_PRODUCT_PROFILE
N K 2 16,178
DONALD
PAGE 3,450,209 N 932,120
9,999
DONALD RWU_PAGE
434 N 8
7,355
DONALD PAGE_IMAGE
18,067 N 1,104 5,368
DONALD SUBSCRIPTION
476 N K 192
2,087
DONALD
PRINT_PAGE_RANGE
10 N K 32
874
The optimizer_index_caching parameter
The optimizer_index_caching parameter is
a percentage parameter with valid values between zero and 100. This
parameter lets you adjust the behavior of the cost-based optimizer to
select nested loop joins more often or less often. The cost of executing
a nested loop join where an index is used to access the inner table is
highly dependent on the caching of that index in the buffer cache. The
amount of index caching depends on factors, such as the load on the
system and the block access patterns of different users, that the
optimizer cannot predict. Of course, you may cache an index by placing
the data block in the KEEP pool, thereby ensuring that the blocks are
always cached.
Setting optimizer_index_caching to a
higher percentage makes nested loop joins look less expensive to the
optimizer, which will be more likely to pick nested loop joins over hash
or sort merge joins.
The default value for the
optimizer_index_caching parameter is 0, which gives the highest
preference to hash joins and sort merge joins. Resetting this parameter
can be very dangerous if you are not using stored outlines because it
could change the execution plans for thousands of SQL statements. Also,
because the cost-based optimizer will generally only invoke sort merge
joins when there are no indexes on the joined tables, this parameter has
the most effect on the invocation of hash joins.
According to the
Oracle documentation:
"OPTIMIZER_INDEX_CACHING favors using selective
indexes. That is, if you use a relatively low value for this parameter,
the optimizer effectively models the caches of all non-leaf index
blocks.
In this case, the optimizer bases the cost of using this index
primarily on the basis of its selectivity. Thus, by setting
OPTIMIZER_INDEX_CACHING to a low value, you achieve the desired modeling
of the index caching without over using possibly undesirable indexes
that have poor selectivity."