Issuu on Google+

Keeping a Table in Memory

Administration Tips

How do I keep a table in memory? The short answer is: you can't. Packages and procedures can be kept in the Library Cache of the shared pool: execute dbms_shared_pool.keep('name_of_package') will guarantee that the named package or procedure will never age out of the Library Cache. But table data is stored in the Buffer Cache, not the Library Cache, and there is no equivalent to the 'keep' procedure to keep it there. Nor, frankly, is there much need to. The Buffer Cache is managed by the "Least Recently Used" list. Blocks which are frequently used (i.e., are useful to many Users) will be at the Most Recently Used (MRU) end of the LRU list. Deeply unpopular blocks which are seldom used will be at the Least Recently Used (LRU) end of the list. When Oracle has to choose which blocks to age out of the Buffer Cache to make room for new arrivals, it chooses the ones at the LRU end of the LRU list. So, if your table is worth keeping in memory, because it is hugely important to your application and is therefore constantly accessed, it will tend to stay in memory automatically, because its blocks will always be at the MRU end of the LRU list. Forcing an unpopular table to be "kept" in the buffer cache would simply be a waste of buffers. That said, it is possible for a popular table to be 'washed out' of the Buffer Cache because some looney decides to do a 'select * from enormous_table' -we need to find room for a bazillion new blocks of data, there aren't enough free buffers, so we just flush the entire LRU list (MRU end and all) to make as much room as we can. Bye-bye useful table blocks. Can that be stopped? Sort of... but Oracle even has a mechanism for trying to avoid this problem too. Usually, when Oracle reads a block of data off disk, it (naturally enough) places it onto the MRU end of the LRU list (it's the most recently touched block, after all). But any full table scans you do have the blocks they touch placed around half-way down the LRU list. That's designed to prevent any 'select *' queries from flushing out the entire LRU list, but can't guarantee that a particularly large full tablescan won't nevertheless be forced to flush the entire list. Introduced in Oracle 8.0, however, was the concept of dividing your Buffer Cache into separate Buffer Pools. There are three possible: the DEFAULT pool (which behaves exactly as an undivided Buffer Cache would), the RECYCLE pool (which is designed to flush blocks out of the Cache as quickly as possible) and the KEEP pool (which is designed to allow blocks to hang around in memory for as long as possible). You must always have a DEFAULT pool, but whether you have both a RECYCLE and a KEEP is up to you: either or both is acceptable.

Copyright Š Howard Rogers 2001

10/17/2001

Page 1 of 3


Keeping a Table in Memory

Administration Tips

The first thing to say about this, however, is that the KEEP pool provides no guarantees: if a large full tablescan inadvertently goes through the KEEP pool, it will still flush the entire pool of its more useful buffers. To set up the multiple pools in Oracle 8.0 or Oracle 8.1, you configure a few init.ora parameters (all aspects of Buffer Cache management have changed significantly in Oracle 9i). DB_BLOCK_LRU_LATCHES sets up the total number of latches available to manage the Buffer Cache (each pool needs its own set of latches) DB_BLOCK_BUFFERS sets up the total number of buffers. Without further qualification, they all belong to the DEFAULT pool. BUFFER_POOL_KEEP sets up the number of buffers to be allocated to the KEEP pool, taking those buffers out of the total previously set by DB_BLOCK_BUFFERS. It also specifies how many of the total available latches should be used to manage this pool. BUFFER_POOL_RECYCLE does the same for the RECYCLE pool. Again, the number of buffers specified here comes from the total pool of buffers allocated by DB_BLOCK_BUFFERS, and it also specifies a number of latches to manage the pool. You might, for example, set up four init.ora lines like this: DB_BLOCK_LRU_LATCHES=6 DB_BLOCK_BUFFERS=20000 BUFFER_POOL_KEEP=(BUFFERS:12000, LRU_LATCHES:3) BUFFER_POOL_RECYCLE=(BUFFERS:2000, LRU_LATCHES:1) ...and that will mean there are 20,000 buffers in total, of which 12,000 are assigned to the KEEP pool,managed by 3 latches; 2,000 are allocated to the RECYCLE pool, managed by a single latch; and (by implication) 6,000 buffers are left for the DEFAULT pool, managed by 2 latches. (Note that the syntax changed between 8.0 and 8i -the above example works for 8i only. In Oracle 8.0, you the syntax was simply "buffer_pool_keep=12000" and so on with no mention of the latches). Note that a latch must manage at least 50 buffers, so you couldn't have a line reading, for example: BUFFER_POOL_KEEP=(buffers:100, lru_latches 3) -because that would require at least 150 buffers. Having set up a number of different buffer pools, you have then to tell Oracle to which pool blocks from a particular table should be sent. If you miss out this step, then a table's blocks will always be sent to the DEFAULT pool by, er... default. You can do this at table (or index) creation time. For example: Copyright Š Howard Rogers 2001

10/17/2001

Page 2 of 3


Keeping a Table in Memory

CREATE

Administration Tips

TABLE ALBUM(

PHOTOID NUMBER, PHOTODESC CHAR(15))

(BUFFER_POOL TABLESPACE DATA4;

STORAGE

RECYCLE)

Blocks from this table will now always be loaded into the RECYCLE pool (and if, incidentally, you haven't actually defined such a pool, its blocks will be loaded into the DEFAULT pool instead). You can also change a table (or index) to use a particular pool after it's already been created: ALTER ALTER

(BUFFER_POOL KEEP); STORAGE (BUFFER_POOL KEEP);

TABLE MUSIC STORAGE INDEX MUSIC_PK

What tables and indexes should be directed to the RECYCLE pool? Basically, large ones that are subject to lots of random reads (the random reads is important: it means that the blocks Frank reads are unlikely to be needed by Scott when he does some reads later). A table which is around twice the size of the entire DEFAULT pool subject to random reads is a prime candidate -using our parameters above, and assuming an 8K block size, that would mean that any tables bigger than (2 x 6000 x 8)K would be a good candidate (by my calculations, that's around 96M). How about the KEEP pool? What tables and indexes should go in there? Relatively small tables that are frequently accessed in their entirety are good candidates here. The standard advice is that a frquently-used table which is smaller than around 10% of the DEFAULT pool is a prime candidate (again, using our earlier init.ora parameters, that would suggest tables smaller than around 5M would be KEEP material). By setting up multiple pools in the Buffer Cache in this way, and then making sure big tables are directed to the RECYCLE pool whilst small ones go to the KEEP pool, you help minimise the chances of a huge tablescan flushing out a small, useful table from the cache (since the scan will be flushing the RECYCLE pool like crazy, and not touching the stuff in the KEEP pool at all). But you can never stop a huge table, accidentally assigned to the KEEP pool, from flushing all the small tables out. You might also check out the tip on "How useful is the CACHE clause?", since that is frequently touted as a means of achieving the 'pinning' of tables in memory. It isn't any such thing, of course.

Copyright Š Howard Rogers 2001

10/17/2001

Page 3 of 3


keep