This article describes what issues affect the performance of the buffer cache and DBWR
(database writer) in Oracle releases 7.1 to 9.2 inclusive. The notes here are particularly important
if your system shows any of the following:
Latch contention for the 'cache buffers lru chain' or the "cache buffer chain" latch
Lots of time spent waiting for "free buffer waits" or "Buffer busy waits"
In Oracle 9i it is possible to use the "Dynamic Buffer Cache Advisory feature" which enables
and disables statistic gathering for predicting the behaviour of the buffer cache with different
cache sizes. Keep in mind that enabling this feature causes CPU and memory overheads in the
system, hence it is recommended to use it only while the system is being monitored rather than
keeping it enabled permanently.
V$DB_CACHE_ADVICE view is populated when the DB_CACHE_ADVICE parameter is
enabled. This view shows the simulated miss rates for a range of potential buffer cache
sizes.Each cache size simulated has its own row in this view, with the predicted physical I/O
activity that would take place for that size. The DB_CACHE_ADVICE parameter is dynamic, so
the advisory can be enabled and disabled dynamically to allow you to collect advisory data for
specific workloads.
See Note:148511.1 - Oracle9i NF: Dynamic Buffer Cache Advisory, to learn how to configure
and use this feature.
The following sections describe things that affect the rate at which buffers in the cache are used.
Execution Plans
By far the biggest factor influencing the rate at which buffers are used are the execution plans of
the SQL statements issued by the application. If a statement performs 10000 block gets rather
than 100 when executing a statement it will not only be slower itself but can affect other users.
Eg: Consider a statement like:
select * from employee where empid=1023 and gender='MALE';
If EMPLOYEE is a large table and this statement always uses the GENDER index rather than
the EMPID index then you scan LOTS of blocks (from the GENDER index) causing them to be
read into the cache (or moved up the LRU if already there). This pushes other blocks, including
dirty blocks, further down the LRU list.
Sorting and Sort Parameters
Sorting within Oracle is described in detail in other articles. Here we focus on the impact on the
buffer cache and DBWR. Sort operations use up to SORT_AREA_SIZE bytes of memory. If a
sort can be performed within this amount of memory and the result set fits within
SORT_AREA_RETAINED_SIZE then there is no need to start writing blocks to disk. If more
sortspace is needed it is then necessary to use a TEMPORARY segment on disk to accommodate
the intermediate sort runs and/or the sort results . There are 2 ways sort blocks can be sent to
disk:
via the buffer cache (and then DBWR)
Using sort direct writes
The first of these is often the default, and in Oracle 7.1 is the only option available. Sort blocks
are placed into the buffer cache thus aging all other blocks. When the sort blocks reach the LRU
end of the least recently used list DBWR will flush them to disk. This can impact the
performance for everyone else as private sort blocks (sort blocks are of no use to anyone else)
can flood DBWR and age blocks in the cache more quickly.
In Oracle 7.2 the parameter SORT_DIRECT_WRITES can be set to cause processes to write sort
blocks direct to disk avoiding the buffer cache. It is generally desirable to set
SORT_DIRECT_WRITES to TRUE to ensure sort blocks do not impact the buffer cache.
Note 1: Setting SORT_DIRECT_WRITES=TRUE causes additional memory to be allocated for
the session.
Note 2: In a lightly loaded environment SORT_DIRECT_WRITES may cause an individual job
to take slightly longer ! Consider that when blocks are placed in the buffer cache it is acting
almost like a memory extension to that process as "GETs" of sort blocks may be satisfied from
the cache rather than from disk.
Since Oracle 8.1 the parameter SORT_DIRECT_WRITES became obsolete and direct writes are
always used for sort operations that do not fit into the sort area size. See Note:135223.1
CACHED Tables and Full Table Scans
It is possible to mark tables within Oracle to be cached using the CACHE option of the CREATE
or ALTER TABLE commands. Provided the table is within CACHE_SIZE_THRESHOLD then
this causes the blocks of full scans of that table to be placed at the MRU (most recently used) end
of the LRU aging other blocks in the cache. Inappropriate caching of tables can thus contribute
to problems with the buffer cache - take care with this option.
The parameter CACHE_SIZE_THRESHOLD is obsoleted in 8.1. In Oracle8i the use of multiple
buffer pools is intended to allow objects to be cached without using this parameter.
In Oracle9i onwards Oracle internally decides whether to cache blocks from table scans in the
buffer cache (or not) based on the cache size and the number of blocks expected to be visited.
More details on this can be read in Note:787373.1.
Data Clustering
Data clustering can affect the number of blocks that queries have to visit to find the result set.
This can be as simple as the PCTFREE and PCTUSED attributes causing fewer rows per block
than is optimal for the application.
A less obvious issue which can affect the IO rates is how well data is clustered physically. Eg:
Assume that you frequently fetch rows from a table where a column is between two values via an
index scan. If there are 100 rows in each index block then the two extremes are:
Each of the table rows is in a different physical block (100 blocks need to be read for each
index block)
The table rows are all located in the few adjacent blocks (a handful of blocks need to be read
for each index block)
Pre-sorting or reorganizing data can help to tackle this in severe situations. Adding an extra
column to an index may eliminate data block access altogether if the queries use this extra
column frequently in their WHERE clause.
Parallel Query
Some operations can be performed much faster using the parallel query features of Oracle7/8/9.
These may benefit the buffer cache as parallel queries can perform direct reads avoiding the
buffer cache - ie: They can read direct from disk into private process memory. Nb: This only
occurs for certain access paths in a query.
Latches:
Please refers to Note:22908.1 for a complete discussion on detecting and resolving latch
contention.
Wait events:
Check for 'right-hand-indexes' (indexes that get inserted into at the same
point by many processes). You can use reverse key indexes to distribute
the different information.
Extent size too small can cause contention on the header when the table
grows regularly. Consider increasing the extent size for the table.
undo header:
undo block:
Oracle Bugs
The first diagnostic step to resolve this behavior is to apply the latest patchset available in your
platform. Most of the buffer cache issues related to BUGs can be avoided by applying these
patchsets. The following table summarize the most common BUGs related to buffer cache
problems, possible workarounds and the patchset that fixes the problem.
BUG
Description
Bug:207952 free buffer waits / LRU latch contention
Workaround
Fixed
Not
8174, 9013, 9201
6
possible on write intensive systems.
available
Bug:196736 Increased index block gets / "cache buffer Not
3
chains" contention in 8i/9i.
available
If you shrink a buffer pool by a certain
Bug:226809 amount and later try to grow the shared
Not
8
pool by the same amount and the grow mayavailable
fail with an "insufficient memory" error.