Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
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:
- Page 339 and 340: 294 CHAPTER 9 ■ REDO AND UNDO row
- Page 341 and 342: 296 CHAPTER 9 ■ REDO AND UNDO If
- Page 343 and 344: 298 CHAPTER 9 ■ REDO AND UNDO ops
- Page 345 and 346: 300 CHAPTER 9 ■ REDO AND UNDO Inv
- Page 347 and 348: 302 CHAPTER 9 ■ REDO AND UNDO The
- Page 349 and 350: 304 CHAPTER 9 ■ REDO AND UNDO 41
- Page 351 and 352: 306 CHAPTER 9 ■ REDO AND UNDO ins
- Page 353 and 354: 308 CHAPTER 9 ■ REDO AND UNDO So,
- Page 355 and 356: 310 CHAPTER 9 ■ REDO AND UNDO ops
- Page 357 and 358: 312 CHAPTER 9 ■ REDO AND UNDO ops
- Page 359 and 360: 314 CHAPTER 9 ■ REDO AND UNDO •
- Page 361 and 362: 316 CHAPTER 9 ■ REDO AND UNDO ...
- Page 363 and 364: 318 CHAPTER 9 ■ REDO AND UNDO •
- Page 365 and 366: 320 CHAPTER 9 ■ REDO AND UNDO bac
- Page 367 and 368: 322 CHAPTER 9 ■ REDO AND UNDO As
- Page 369 and 370: 324 CHAPTER 9 ■ REDO AND UNDO ops
- Page 371 and 372: 326 CHAPTER 9 ■ REDO AND UNDO wil
- Page 373 and 374: 328 CHAPTER 9 ■ REDO AND UNDO Thi
- Page 375 and 376: 330 CHAPTER 9 ■ REDO AND UNDO ops
- Page 377 and 378: 332 CHAPTER 9 ■ REDO AND UNDO Whe
- Page 379 and 380: 334 CHAPTER 9 ■ REDO AND UNDO Tha
- Page 381 and 382: 336 CHAPTER 9 ■ REDO AND UNDO tou
- Page 383 and 384: 338 CHAPTER 10 ■ DATABASE TABLES
- Page 385 and 386: 340 CHAPTER 10 ■ DATABASE TABLES
- Page 387 and 388: 342 CHAPTER 10 ■ DATABASE TABLES
- Page 389: 344 CHAPTER 10 ■ DATABASE TABLES
- Page 393 and 394: 348 CHAPTER 10 ■ DATABASE TABLES
- Page 395 and 396: 350 CHAPTER 10 ■ DATABASE TABLES
- Page 397 and 398: 352 CHAPTER 10 ■ DATABASE TABLES
- Page 399 and 400: 354 CHAPTER 10 ■ DATABASE TABLES
- Page 401 and 402: 356 CHAPTER 10 ■ DATABASE TABLES
- Page 403 and 404: 358 CHAPTER 10 ■ DATABASE TABLES
- Page 405 and 406: 360 CHAPTER 10 ■ DATABASE TABLES
- Page 407 and 408: 362 CHAPTER 10 ■ DATABASE TABLES
- Page 409 and 410: 364 CHAPTER 10 ■ DATABASE TABLES
- Page 411 and 412: 366 CHAPTER 10 ■ DATABASE TABLES
- Page 413 and 414: 368 CHAPTER 10 ■ DATABASE TABLES
- Page 415 and 416: 370 CHAPTER 10 ■ DATABASE TABLES
- Page 417 and 418: 372 CHAPTER 10 ■ DATABASE TABLES
- Page 419 and 420: 374 CHAPTER 10 ■ DATABASE TABLES
- Page 421 and 422: 376 CHAPTER 10 ■ DATABASE TABLES
- Page 423 and 424: 378 CHAPTER 10 ■ DATABASE TABLES
- Page 425 and 426: 380 CHAPTER 10 ■ DATABASE TABLES
- Page 427 and 428: 382 CHAPTER 10 ■ DATABASE TABLES
- Page 429 and 430: 384 CHAPTER 10 ■ DATABASE TABLES
- Page 431 and 432: 386 CHAPTER 10 ■ DATABASE TABLES
- Page 433 and 434: 388 CHAPTER 10 ■ DATABASE TABLES
- Page 435 and 436: 390 CHAPTER 10 ■ DATABASE TABLES
- Page 437 and 438: 392 CHAPTER 10 ■ DATABASE TABLES
- Page 439 and 440: 394 CHAPTER 10 ■ DATABASE TABLES
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: