Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 10 ■ DATABASE TABLES 345 logs are sized appropriately, indexes won’t be slowing things down, and I’m running on a machine with two hyperthreaded Xeon CPUs—this should run fast. What I discovered afterward, however, is the following: Snap Id Snap Time Sessions Curs/Sess Comment --------- ------------------ -------- --------- ------------------- Begin Snap: 793 29-Apr-05 13:45:36 15 3.9 End Snap: 794 29-Apr-05 13:46:34 15 5.7 Elapsed: 0.97 (mins) Top 5 Timed Events ~~~~~~~~~~~~~~~~~~ % Total Event Waits Time (s) Call Time -------------------------------------------- ------------ ----------- --------- CPU time 165 53.19 buffer busy waits 368,698 119 38.43 log file parallel write 1,323 21 6.86 latch: cache buffers chains 355 2 .67 enq: HW - contention 2,828 1 .24 I collectively waited 119 seconds, or about 24 seconds per session, on buffer busy waits. These waits are caused entirely by the fact that there are not enough freelists configured on my table for the type of concurrent activity that is taking place. I can eliminate most of that wait time easily, just by creating the table with multiple freelists: ops$tkyte@ORA10GR1> create table t ( x int, y char(50) ) 2 storage( freelists 5 ) tablespace MSSM; Table created. or by altering the object: ops$tkyteORA10GR1> alter table t storage ( FREELISTS 5 ); Table altered. You will find that the buffer busy waits goes way down, and the amount of CPU needed (since you are doing less work here; competing for a latched data structure can really burn CPU) also goes down along with the elapsed time: Snap Id Snap Time Sessions Curs/Sess Comment --------- ------------------ -------- --------- ------------------- Begin Snap: 809 29-Apr-05 14:04:07 15 4.0 End Snap: 810 29-Apr-05 14:04:41 14 6.0 Elapsed: 0.57 (mins) Top 5 Timed Events ~~~~~~~~~~~~~~~~~~ % Total Event Waits Time (s) Call Time -------------------------------------------- ------------ ----------- --------- CPU time 122 74.66

346 CHAPTER 10 ■ DATABASE TABLES buffer busy waits 76,538 24 14.94 log file parallel write 722 14 8.45 latch: cache buffers chains 144 1 .63 enq: HW - contention 678 1 .46 What you want to do for a table is try to determine the maximum number of concurrent (truly concurrent) inserts or updates that will require more space. What I mean by “truly concurrent” is how often you expect two people at exactly the same instant to request a free block for that table. This is not a measure of overlapping transactions; it is a measure of how many sessions are doing inserts at the same time, regardless of transaction boundaries. You want to have about as many freelists as concurrent inserts into the table to increase concurrency. You should just set freelists really high and then not worry about it, right? Wrong—of course, that would be too easy. When you use multiple freelists, there is a master freelist and process freelists. If a segment has a single freelist, then the master and process freelists are one and the same thing. If you have two freelists, you’ll really have one master freelist and two process freelists. A given session will be assigned to a single process freelist based on a hash of its session ID. Now, each process freelist will have very few blocks on it—the remaining free blocks are on the master freelist. As a process freelist is used, it will pull a few blocks from the master freelist as needed. If the master freelist cannot satisfy the space requirement, then Oracle will advance the HWM and add empty blocks to the master freelist. So, over time, the master freelist will fan out its storage over the many process freelists (again, each of which has only a few blocks on it). So, each process will use a single process freelist. It will not go from process freelist to process freelist to find space. This means that if you have ten process freelists on a table, and the one your process is using exhausts the free buffers on its list, it will not go to another process freelist for space—even if the other nine process freelists have five blocks each (45 blocks in total), it will go to the master freelist. Assuming the master freelist cannot satisfy the request for a free block, it would cause the table to advance the HWM or, if the table’s HWM cannot be advanced (all the space is used), to extend (to get another extent). It will then continue to use the space on its freelist only (which is no longer empty). There is a tradeoff to be made with multiple freelists. On one hand, use of multiple freelists is a huge performance booster. On the other hand, it will probably cause the table to use slightly more disk space than absolutely necessary. You will have to decide which is less bothersome in your environment. Do not underestimate the usefulness of the FREELISTS parameter, especially since you can alter it up and down at will with Oracle 8.1.6 and later. What you might do is alter it to a large number to perform some load of data in parallel with the conventional path mode of SQL*Loader. You will achieve a high degree of concurrency for the load with minimum waits. After the load, you can reduce the value to some more reasonable, day-to-day number. The blocks on the many existing freelists will be merged into the one master freelist when you alter the space down. Another way to solve the previously mentioned issue of buffer busy waits is to use an ASSM managed tablespace. If you take the preceding example and create the table T in an ASSM managed tablespace as follows:

346<br />

CHAPTER 10 ■ DATABASE TABLES<br />

buffer busy waits 76,538 24 14.94<br />

log file parallel write 722 14 8.45<br />

latch: cache buffers chains 144 1 .63<br />

enq: HW - contention 678 1 .46<br />

What you want to do for a table is try to determine the maximum number of concurrent<br />

(truly concurrent) inserts or updates that will require more space. What I mean by “truly concurrent”<br />

is how often you expect two people at exactly the same instant to request a free block<br />

for that table. This is not a measure of overlapping transactions; it is a measure of how many<br />

sessions are doing inserts at the same time, regardless of transaction boundaries. You want to<br />

have about as many freelists as concurrent inserts into the table to increase concurrency.<br />

You should just set freelists really high <strong>and</strong> then not worry about it, right? Wrong—of<br />

course, that would be too easy. When you use multiple freelists, there is a master freelist <strong>and</strong><br />

process freelists. If a segment has a single freelist, then the master <strong>and</strong> process freelists are<br />

one <strong>and</strong> the same thing. If you have two freelists, you’ll really have one master freelist <strong>and</strong> two<br />

process freelists. A given session will be assigned to a single process freelist based on a hash of<br />

its session ID. Now, each process freelist will have very few blocks on it—the remaining free<br />

blocks are on the master freelist. As a process freelist is used, it will pull a few blocks from the<br />

master freelist as needed. If the master freelist cannot satisfy the space requirement, then<br />

<strong>Oracle</strong> will advance the HWM <strong>and</strong> add empty blocks to the master freelist. So, over time, the<br />

master freelist will fan out its storage over the many process freelists (again, each of which has<br />

only a few blocks on it). So, each process will use a single process freelist. It will not go from<br />

process freelist to process freelist to find space. This means that if you have ten process freelists<br />

on a table, <strong>and</strong> the one your process is using exhausts the free buffers on its list, it will<br />

not go to another process freelist for space—even if the other nine process freelists have five<br />

blocks each (45 blocks in total), it will go to the master freelist. Assuming the master freelist<br />

cannot satisfy the request for a free block, it would cause the table to advance the HWM or, if<br />

the table’s HWM cannot be advanced (all the space is used), to extend (to get another extent).<br />

It will then continue to use the space on its freelist only (which is no longer empty). There is<br />

a tradeoff to be made with multiple freelists. On one h<strong>and</strong>, use of multiple freelists is a huge<br />

performance booster. On the other h<strong>and</strong>, it will probably cause the table to use slightly more<br />

disk space than absolutely necessary. You will have to decide which is less bothersome in your<br />

environment.<br />

Do not underestimate the usefulness of the FREELISTS parameter, especially since you<br />

can alter it up <strong>and</strong> down at will with <strong>Oracle</strong> 8.1.6 <strong>and</strong> later. What you might do is alter it to a<br />

large number to perform some load of data in parallel with the conventional path mode of<br />

SQL*Loader. You will achieve a high degree of concurrency for the load with minimum waits.<br />

After the load, you can reduce the value to some more reasonable, day-to-day number. The<br />

blocks on the many existing freelists will be merged into the one master freelist when you alter<br />

the space down.<br />

Another way to solve the previously mentioned issue of buffer busy waits is to use an<br />

ASSM managed tablespace. If you take the preceding example <strong>and</strong> create the table T in<br />

an ASSM managed tablespace as follows:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!