05.11.2015 Views

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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

334<br />

CHAPTER 9 ■ REDO AND UNDO<br />

That table will have lots of blocks as we get about six or seven rows per block using that<br />

big data field. Next, we’ll create the small table that the many little transactions will modify:<br />

ops$tkyte@ORA10G> create table small ( x int, y char(500) );<br />

Table created.<br />

ops$tkyte@ORA10G> insert into small select rownum, 'x' from all_users;<br />

38 rows created.<br />

ops$tkyte@ORA10G> commit;<br />

Commit complete.<br />

ops$tkyte@ORA10G> exec dbms_stats.gather_table_stats( user, 'SMALL' );<br />

PL/SQL procedure successfully completed.<br />

Now, we’ll dirty up that big table. We have a very small undo tablespace, so we’ll want to<br />

update as many blocks of this big table as possible, all while generating the least amount of<br />

undo possible. We’ll be using a fancy UPDATE statement to do that. Basically, the following subquery<br />

is finding the “first” rowid of a row on every block. That subquery will return a rowid for<br />

each <strong>and</strong> every database block identifying a single row on it. We’ll update that row, setting a<br />

VARCHAR2(1) field. This will let us update all of the blocks in the table (some 8,000 plus in the<br />

example), flooding the buffer cache with dirty blocks that will have to be written out (we have<br />

room for only 500 right now). We’ll make sure we are using that small undo tablespace as well.<br />

To accomplish this <strong>and</strong> not exceed the capacity of our undo tablespace, we’ll craft an UPDATE<br />

statement that will update just the “first row” on each block. The ROW_NUMBER() built-in analytic<br />

function is instrumental in this operation; it assigns the number 1 to the “first row” by<br />

database block in the table, which would be the single row on the block we would update:<br />

ops$tkyte@ORA10G> alter system set undo_tablespace = undo_small;<br />

System altered.<br />

ops$tkyte@ORA10G> update big<br />

2 set temporary = temporary<br />

3 where rowid in<br />

4 (<br />

5 select r<br />

6 from (<br />

7 select rowid r, row_number() over<br />

(partition by dbms_rowid.rowid_block_number(rowid) order by rowid) rn<br />

8 from big<br />

9 )<br />

10 where rn = 1<br />

11 )<br />

12 /<br />

8045 rows updated.<br />

ops$tkyte@ORA10G> commit;<br />

Commit complete.

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

Saved successfully!

Ooh no, something went wrong!