Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
CHAPTER 4 ■ MEMORY STRUCTURES 141 Block Buffer Cache So far, we have looked at relatively small components of the SGA. Now we are going to look at one that is possibly huge in size. The block buffer cache is where Oracle stores database blocks before writing them to disk and after reading them in from disk. This is a crucial area of the SGA for us. Make it too small and our queries will take forever to run. Make it too big and we’ll starve other processes (e.g., we won’t leave enough room for a dedicated server to create its PGA, and we won’t even get started). In earlier releases of Oracle, there was a single block buffer cache, and all blocks from any segment went into this single area. Starting with Oracle 8.0, we had three places to store cached blocks from individual segments in the SGA: • Default pool: The location where all segment blocks are normally cached. This is the original—and previously only—buffer pool. • Keep pool: An alternate buffer pool where by convention you would assign segments that were accessed fairly frequently, but still got aged out of the default buffer pool due to other segments needing space. • Recycle pool: An alternate buffer pool where by convention you would assign large segments that you access very randomly, and which would therefore cause excessive buffer flushing but would offer no benefit, because by the time you wanted the block again it would have been aged out of the cache. You would separate these segments out from the segments in the Default and Keep pools so that they would not cause those blocks to age out of the cache. Note that in the Keep and Recycle pool descriptions I used the phrase “by convention.” There is nothing in place to ensure that you use neither the Keep pool nor the Recycle pool in the fashion described. In fact, the three pools manage blocks in a mostly identical fashion; they do not have radically different algorithms for aging or caching blocks. The goal here was to give the DBA the ability to segregate segments to hot, warm, and do not care to cache areas. The theory was that objects in the Default pool would be hot enough (i.e., used enough) to warrant staying in the cache all by themselves. The cache would keep them in memory since they were very popular blocks. You might have had some segments that were fairly popular, but not really hot; these would be considered the warm blocks. These segments’ blocks could get flushed from the cache to make room for some blocks you used infrequently (the “do not care to cache” blocks). To keep these warm segments blocks cached, you could do one of the following: • Assign these segments to the Keep pool, in an attempt to let the warm blocks stay in the buffer cache longer. • Assign the “do not care to cache” segments to the Recycle pool, keeping the Recycle pool fairly small so as to let the blocks come into the cache and leave the cache rapidly (decrease the overhead of managing them all). This increased the management work the DBA had to perform, as there were three caches to think about, size, and assign objects to. Remember also that there is no sharing between them, so if the Keep pool has lots of unused space, it won’t give it to the overworked Default or Recycle pool. All in all, these pools were generally regarded as a very fine, low-level tuning
142 CHAPTER 4 ■ MEMORY STRUCTURES device, only to be used after most all other tuning alternatives had been looked at (if I could rewrite a query to do one-tenth the I/O rather then set up multiple buffer pools, that would be my choice!). Starting in Oracle9i, the DBA had up to four more optional caches, the db_Nk_caches, to consider in addition to the Default, Keep, and Recycle pools. These caches were added in support of multiple blocksizes in the database. Prior to Oracle9i, a database would have a single blocksize (typically 2KB, 4KB, 8KB, 16KB, or 32KB). Starting with Oracle9i, a database can have a default blocksize, which is the size of the blocks stored in the Default, Keep, or Recycle pool, as well as up to four nondefault blocksizes, as explained in Chapter 3. The blocks in these buffer caches are managed in the same way as the blocks in the original Default pool—there are no special algorithm changes for them either. Let’s now move on to cover how the blocks are managed in these pools. Managing Blocks in the Buffer Cache For simplicity, assume in this discussion that there is just a single Default pool. Because the other pools are managed in the same way, we need only discuss one of them. The blocks in the buffer cache are basically managed in a single place with two different lists pointing at them: • The dirty list of blocks that need to be written by the database block writer (DBWn; we’ll take a look at that process a little later) • A list of nondirty blocks The list of nondirty blocks used to be a Least Recently Used (LRU) list in Oracle 8.0 and before. Blocks were listed in order of use. The algorithm has been modified slightly in Oracle8i and in later versions. Instead of maintaining the list of blocks in some physical order, Oracle employs a touch count algorithm, which effectively increments a counter associated with a block as you hit it in the cache. This count is not incremented every time you hit the block, but about once every three seconds—if you hit it continuously. You can see this algorithm at work in one of the truly magic sets of tables: the X$ tables. The X$ tables are wholly undocumented by Oracle, but information about them leaks out from time to time. The X$BH table shows information about the blocks in the block buffer cache (which offers more information than the documented V$BH view). Here, we can see the touch count get incremented as we hit blocks. We can run the following query against that view to find the five “currently hottest blocks” and join that information to the DBA_OBJECTS view to see what segments they belong to. The query orders the rows in X$BH by the TCH (touch count) column and keeps the first five. Then we join the X$BH information to DBA_OBJECTS by X$BH.OBJ to DBA_OBJECTS.DATA_OBJECT_ID: sys@ORA10G> select tch, file#, dbablk, 2 case when obj = 4294967295 3 then 'rbs/compat segment' 4 else (select max( '('||object_type||') ' || 5 owner || '.' || object_name ) || 6 decode( count(*), 1, '', ' maybe!' ) 7 from dba_objects
- Page 136 and 137: CHAPTER 3 ■ FILES 91 Redundant Ar
- Page 138 and 139: CHAPTER 3 ■ FILES 93 (data from m
- Page 140 and 141: CHAPTER 3 ■ FILES 95 dictionary t
- Page 142 and 143: CHAPTER 3 ■ FILES 97 ■Note df i
- Page 144 and 145: CHAPTER 3 ■ FILES 99 “accidenta
- Page 146 and 147: CHAPTER 3 ■ FILES 101 So, at the
- Page 148 and 149: CHAPTER 3 ■ FILES 103 Password Fi
- Page 150 and 151: CHAPTER 3 ■ FILES 105 USER is "SY
- Page 152 and 153: CHAPTER 3 ■ FILES 107 Flashback L
- Page 154 and 155: CHAPTER 3 ■ FILES 109 of the requ
- Page 156 and 157: CHAPTER 3 ■ FILES 111 IMPDP, howe
- Page 158 and 159: CHAPTER 3 ■ FILES 113 tkyte@ORA10
- Page 160 and 161: CHAPTER 4 ■ ■ ■ Memory Struct
- Page 162 and 163: CHAPTER 4 ■ MEMORY STRUCTURES 117
- Page 164 and 165: CHAPTER 4 ■ MEMORY STRUCTURES 119
- Page 166 and 167: CHAPTER 4 ■ MEMORY STRUCTURES 121
- Page 168 and 169: CHAPTER 4 ■ MEMORY STRUCTURES 123
- Page 170 and 171: CHAPTER 4 ■ MEMORY STRUCTURES 125
- Page 172 and 173: CHAPTER 4 ■ MEMORY STRUCTURES 127
- Page 174 and 175: CHAPTER 4 ■ MEMORY STRUCTURES 129
- Page 176 and 177: CHAPTER 4 ■ MEMORY STRUCTURES 131
- Page 178 and 179: CHAPTER 4 ■ MEMORY STRUCTURES 133
- Page 180 and 181: CHAPTER 4 ■ MEMORY STRUCTURES 135
- Page 182 and 183: CHAPTER 4 ■ MEMORY STRUCTURES 137
- Page 184 and 185: CHAPTER 4 ■ MEMORY STRUCTURES 139
- Page 188 and 189: CHAPTER 4 ■ MEMORY STRUCTURES 143
- Page 190 and 191: CHAPTER 4 ■ MEMORY STRUCTURES 145
- Page 192 and 193: CHAPTER 4 ■ MEMORY STRUCTURES 147
- Page 194 and 195: CHAPTER 4 ■ MEMORY STRUCTURES 149
- Page 196 and 197: CHAPTER 4 ■ MEMORY STRUCTURES 151
- Page 198 and 199: CHAPTER 4 ■ MEMORY STRUCTURES 153
- Page 200 and 201: CHAPTER 5 ■ ■ ■ Oracle Proces
- Page 202 and 203: CHAPTER 5 ■ ORACLE PROCESSES 157
- Page 204 and 205: CHAPTER 5 ■ ORACLE PROCESSES 159
- Page 206 and 207: CHAPTER 5 ■ ORACLE PROCESSES 161
- Page 208 and 209: CHAPTER 5 ■ ORACLE PROCESSES 163
- Page 210 and 211: CHAPTER 5 ■ ORACLE PROCESSES 165
- Page 212 and 213: CHAPTER 5 ■ ORACLE PROCESSES 167
- Page 214 and 215: CHAPTER 5 ■ ORACLE PROCESSES 169
- Page 216 and 217: CHAPTER 5 ■ ORACLE PROCESSES 171
- Page 218 and 219: CHAPTER 5 ■ ORACLE PROCESSES 173
- Page 220 and 221: CHAPTER 5 ■ ORACLE PROCESSES 175
- Page 222 and 223: CHAPTER 5 ■ ORACLE PROCESSES 177
- Page 224 and 225: CHAPTER 5 ■ ORACLE PROCESSES 179
- Page 226 and 227: CHAPTER 5 ■ ORACLE PROCESSES 181
- Page 228 and 229: CHAPTER 6 ■ ■ ■ Locking and L
- Page 230 and 231: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 232 and 233: CHAPTER 6 ■ LOCKING AND LATCHING
- Page 234 and 235: CHAPTER 6 ■ LOCKING AND LATCHING
142<br />
CHAPTER 4 ■ MEMORY STRUCTURES<br />
device, only to be used after most all other tuning alternatives had been looked at (if I could<br />
rewrite a query to do one-tenth the I/O rather then set up multiple buffer pools, that would be<br />
my choice!).<br />
Starting in <strong>Oracle</strong>9i, the DBA had up to four more optional caches, the db_Nk_caches, to<br />
consider in addition to the Default, Keep, <strong>and</strong> Recycle pools. These caches were added in support<br />
of multiple blocksizes in the database. Prior to <strong>Oracle</strong>9i, a database would have a single<br />
blocksize (typically 2KB, 4KB, 8KB, 16KB, or 32KB). Starting with <strong>Oracle</strong>9i, a database can have<br />
a default blocksize, which is the size of the blocks stored in the Default, Keep, or Recycle pool,<br />
as well as up to four nondefault blocksizes, as explained in Chapter 3.<br />
The blocks in these buffer caches are managed in the same way as the blocks in the original<br />
Default pool—there are no special algorithm changes for them either. Let’s now move on<br />
to cover how the blocks are managed in these pools.<br />
Managing Blocks in the Buffer Cache<br />
For simplicity, assume in this discussion that there is just a single Default pool. Because the<br />
other pools are managed in the same way, we need only discuss one of them.<br />
The blocks in the buffer cache are basically managed in a single place with two different<br />
lists pointing at them:<br />
• The dirty list of blocks that need to be written by the database block writer (DBWn; we’ll<br />
take a look at that process a little later)<br />
• A list of nondirty blocks<br />
The list of nondirty blocks used to be a Least Recently Used (LRU) list in <strong>Oracle</strong> 8.0 <strong>and</strong><br />
before. Blocks were listed in order of use. The algorithm has been modified slightly in <strong>Oracle</strong>8i<br />
<strong>and</strong> in later versions. Instead of maintaining the list of blocks in some physical order, <strong>Oracle</strong><br />
employs a touch count algorithm, which effectively increments a counter associated with a<br />
block as you hit it in the cache. This count is not incremented every time you hit the block, but<br />
about once every three seconds—if you hit it continuously. You can see this algorithm at work<br />
in one of the truly magic sets of tables: the X$ tables. The X$ tables are wholly undocumented<br />
by <strong>Oracle</strong>, but information about them leaks out from time to time.<br />
The X$BH table shows information about the blocks in the block buffer cache (which offers<br />
more information than the documented V$BH view). Here, we can see the touch count get<br />
incremented as we hit blocks. We can run the following query against that view to find the five<br />
“currently hottest blocks” <strong>and</strong> join that information to the DBA_OBJECTS view to see what segments<br />
they belong to. The query orders the rows in X$BH by the TCH (touch count) column <strong>and</strong><br />
keeps the first five. Then we join the X$BH information to DBA_OBJECTS by X$BH.OBJ to<br />
DBA_OBJECTS.DATA_OBJECT_ID:<br />
sys@ORA10G> select tch, file#, dbablk,<br />
2 case when obj = 4294967295<br />
3 then 'rbs/compat segment'<br />
4 else (select max( '('||object_type||') ' ||<br />
5 owner || '.' || object_name ) ||<br />
6 decode( count(*), 1, '', ' maybe!' )<br />
7 from dba_objects