Buffer cache hit ratio
The buffer cache hit ratio calculates how often a requested block has been found in the buffer cache without requiring disk access. This ratio is computed using data selected from the dynamic performance view
V$SYSSTAT
. The buffer cache hit ratio can be used to verify the physical I/O as predicted by V$DB_CACHE_ADVICE
.
Calculating the Buffer Cache Hit Ratio
SELECT NAME, VALUE FROM V$SYSSTAT WHERE NAME IN ('db block gets from cache', 'consistent gets from cache', 'physical reads cache');
1 - (('physical reads cache') / ('consistent gets from cache' + 'db block gets from cache')
Interpreting and Using the Buffer Cache Advisory Statistics
There are many factors to examine before considering whether to increase or decrease the buffer cache size. For example, you should examine
V$DB_CACHE_ADVICE
data and the buffer cache hit ratio.
A low cache hit ratio does not imply that increasing the size of the cache would be beneficial for performance. A good cache hit ratio could wrongly indicate that the cache is adequately sized for the workload.
To interpret the buffer cache hit ratio, you should consider the following:
- Repeated scanning of the same large table or index can artificially inflate a poor cache hit ratio. Examine frequently executed SQL statements with a large number of buffer gets, to ensure that the execution plan for such SQL statements is optimal. If possible, avoid repeated scanning of frequently accessed data by performing all of the processing in a single pass or by optimizing the SQL statement.
- If possible, avoid requerying the same data, by caching frequently accessed data in the client program or middle tier.
- Oracle blocks accessed during a long full table scan are put on the tail end of the least recently used (LRU) list and not on the head of the list. Therefore, the blocks are aged out faster than blocks read when performing indexed lookups or small table scans. When interpreting the buffer cache data, poor hit ratios when valid large full table scans are occurring should also be considered.Note:Short table scans are scans performed on tables under a certain size threshold. The definition of a small table is the maximum of 2% of the buffer cache and 20, whichever is bigger.
- In any large database running OLTP applications in any given unit of time, most rows are accessed either one or zero times. On this basis, there might be little purpose in keeping the block in memory for very long following its use.
- A common mistake is to continue increasing the buffer cache size. Such increases have no effect if you are doing full table scans or operations that do not use the buffer cache.
Increasing Memory Allocated to the Buffer Cache
As a general rule, investigate increasing the size of the cache if the cache hit ratio is low and your application has been tuned to avoid performing full table scans.
To increase cache size, first set the
DB_CACHE_ADVICE
initialization parameter to ON
, and let the cache statistics stabilize. Examine the advisory data in theV$DB_CACHE_ADVICE
view to determine the next increment required to significantly decrease the amount of physical I/O performed. If it is possible to allocate the required extra memory to the buffer cache without causing the host operating system to page, then allocate this memory. To increase the amount of memory allocated to the buffer cache, increase the value of the DB_CACHE_SIZE
initialization parameter.
If required, resize the buffer pools dynamically, rather than shutting down the instance to perform this change.
Note:
When the cache is resized significantly (greater than 20 percent), the old cache advisory value is discarded and the cache advisory is set to the new size. Otherwise, the old cache advisory value is adjusted to the new size by the interpolation of existing values.
The
DB_CACHE_SIZE
parameter specifies the size of the default cache for the database's standard block size. To create and use tablespaces with block sizes different than the database's standard block sizes (such as to support transportable tablespaces), you must configure a separate cache for each block size used.
The DB_
n
K_CACHE_SIZE
parameter can be used to configure the nonstandard block size needed (where n
is 2, 4, 8, 16 or 32 and n
is not the standard block size).
Note:
The process of choosing a cache size is the same, regardless of whether the cache is the default standard block size cache, the
KEEP
or RECYCLE
cache, or a nonstandard block size cache.Reducing Memory Allocated to the Buffer Cache
If the cache hit ratio is high, then the cache is probably large enough to hold the most frequently accessed data. Check
V$DB_CACHE_ADVICE
data to see whether decreasing the cache size significantly causes the number of physical I/Os to increase. If not, and if you require memory for another memory structure, then you might be able to reduce the cache size and still maintain good performance. To make the buffer cache smaller, reduce the size of the cache by changing the value for the parameterDB_CACHE_SIZE
.Considering Multiple Buffer Pools
A single default buffer pool is generally adequate for most systems. However, users with detailed knowledge of an application's buffer pool might benefit from configuring multiple buffer pools.
With segments that have atypical access patterns, store blocks from those segments in two different buffer pools: the
KEEP
pool and the RECYCLE
pool. A segment's access pattern may be atypical if it is constantly accessed (that is, hot) or infrequently accessed (for example, a large segment accessed by a batch job only once a day).
Multiple buffer pools let you address these differences. You can use a
KEEP
buffer pool to maintain frequently accessed segments in the buffer cache, and a RECYCLE
buffer pool to prevent objects from consuming unnecessary space in the cache. When an object is associated with a cache, all blocks from that object are placed in that cache. Oracle maintains a DEFAULT
buffer pool for objects that have not been assigned to a specific buffer pool. The default buffer pool is of size DB_CACHE_SIZE
. Each buffer pool uses the same LRU replacement policy (for example, if the KEEP
pool is not large enough to store all of the segments allocated to it, then the oldest blocks age out of the cache).
By allocating objects to appropriate buffer pools, you can:
- Reduce or eliminate I/Os
- Isolate or limit an object to a separate cache
Random Access to Large Segments
A problem can occur with an LRU aging method when a very large segment is accessed with a large or unbounded index range scan. Here, very large means large compared to the size of the cache. Any single segment that accounts for a substantial portion (more than 10%) of nonsequential physical reads can be considered very large. Random reads to a large segment can cause buffers that contain data for other segments to be aged out of the cache. The large segment ends up consuming a large percentage of the cache, but it does not benefit from the cache.
Very frequently accessed segments are not affected by large segment reads because their buffers are warmed frequently enough that they do not age out of the cache. However, the problem affects warm segments that are not accessed frequently enough to survive the buffer aging caused by the large segment reads. There are three options for solving this problem:
- If the object accessed is an index, find out whether the index is selective. If not, tune the SQL statement to use a more selective index.
- Alternatively, you can move the small warm segments into a separate
KEEP
cache that is not used at all for large segments. TheKEEP
cache can be sized to minimize misses in the cache. You can make the response times for specific queries more predictable by putting the segments accessed by the queries in theKEEP
cache to ensure that they do not age out.
Determining Which Segments Have Many Buffers in the Pool
Method 1
The following query counts the number of blocks for all segments that reside in the buffer cache at that point in time. Depending on buffer cache size, this might require a lot of sort space.
COLUMN OBJECT_NAME FORMAT A40 COLUMN NUMBER_OF_BLOCKS FORMAT 999,999,999,999 SELECT o.OBJECT_NAME, COUNT(*) NUMBER_OF_BLOCKS FROM DBA_OBJECTS o, V$BH bh WHERE o.DATA_OBJECT_ID = bh.OBJD AND o.OWNER != 'SYS' GROUP BY o.OBJECT_NAME ORDER BY COUNT(*);
Method 2Use the following steps to determine the percentage of the cache used by an individual object at a given point in time:
- Find the Oracle internal object number of the segment by entering the following query:
SELECT DATA_OBJECT_ID, OBJECT_TYPE FROM DBA_OBJECTS WHERE OBJECT_NAME = UPPER('segment_name');
Because two objects can have the same name (if they are different types of objects), use theOBJECT_TYPE
column to identify the object of interest.- Find the number of buffers in the buffer cache for
SEGMENT_NAME
:
SELECT COUNT(*) BUFFERS FROM V$BH WHERE OBJD = data_object_id_value;
wheredata_object_id_value
is from step 1.- Find the number of buffers in the instance:
SELECT NAME, BLOCK_SIZE, SUM(BUFFERS) FROM V$BUFFER_POOL GROUP BY NAME, BLOCK_SIZE HAVING SUM(BUFFERS) > 0;- Calculate the ratio of buffers to total buffers to obtain the percentage of the cache currently used by SEGMENT_NAME:
% cache used by segment_name = [buffers(Step2)/total buffers(Step3)]Note:This technique works only for a single segment. You must run the query for each partition for a partitioned object.KEEP Pool
If there are certain segments in your application that are referenced frequently, then store the blocks from those segments in a separate cache called theKEEP
buffer pool. Memory is allocated to theKEEP
buffer pool by setting the parameterDB_KEEP_CACHE_SIZE
to the required size. The memory for theKEEP
pool is not a subset of the default pool. Typical segments that can be kept are small reference tables that are used frequently. Application developers and DBAs can determine which tables are candidates.You can check the number of blocks from candidate tables by queryingV$BH
Note:TheNOCACHE
clause has no effect on a table in theKEEP
cache.The goal of theKEEP
buffer pool is to retain objects in memory, thus avoiding I/O operations. The size of theKEEP
buffer pool, therefore, depends on the objects that you want to keep in the buffer cache. You can compute an approximate size for theKEEP
buffer pool by adding together the blocks used by all objects assigned to this pool. If you gather statistics on the segments, you can queryDBA_TABLES.BLOCKS
andDBA_TABLES
.EMPTY_BLOCKS
to determine the number of blocks used.Calculate the hit ratio by taking two snapshots of system performance at different times, using the previous query. Subtract the more recent values forphysical
reads
,block
gets
, andconsistent
gets
from the older values, and use the results to compute the hit ratio.A buffer pool hit ratio of 100% might not be optimal. Often, you can decrease the size of yourKEEP
buffer pool and still maintain a sufficiently high hit ratio. Allocate blocks removed from theKEEP
buffer pool to other buffer pools.Note:If an object grows in size, then it might no longer fit in theKEEP
buffer pool. You will begin to lose blocks out of the cache.Each object kept in memory results in a trade-off. It is beneficial to keep frequently-accessed blocks in the cache, but retaining infrequently-used blocks results in less space for other, more active blocks.RECYCLE Pool
It is possible to configure aRECYCLE
buffer pool for blocks belonging to those segments that you do not want to remain in memory. TheRECYCLE
pool is good for segments that are scanned rarely or are not referenced frequently. If an application accesses the blocks of a very large object in a random fashion, then there is little chance of reusing a block stored in the buffer pool before it is aged out. This is true regardless of the size of the buffer pool (given the constraint of the amount of available physical memory). Consequently, the object's blocks need not be cached; those cache buffers can be allocated to other objects.Memory is allocated to theRECYCLE
buffer pool by setting the parameterDB_RECYCLE_CACHE_SIZE
to the required size. This memory for theRECYCLE
buffer pool is not a subset of the default pool.Do not discard blocks from memory too quickly. If the buffer pool is too small, then blocks can age out of the cache before the transaction or SQL statement has completed execution. For example, an application might select a value from a table, use the value to process some data, and then update the record. If the block is removed from the cache after theSELECT
statement, then it must be read from disk again to perform the update. The block should be retained for the duration of the user transaction.
No comments:
Post a Comment