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.

CHAPTER 11 ■ INDEXES 483<br />

ops$tkyte@ORA10GR1> analyze index t_pk validate structure;<br />

Index analyzed.<br />

ops$tkyte@ORA10GR1> select lf_blks, br_blks, btree_space<br />

2 from index_stats;<br />

LF_BLKS BR_BLKS BTREE_SPACE<br />

---------- ---------- -----------<br />

1 0 7996<br />

This shows the space in the index was reused. As with most myths, however, there is a<br />

nugget of truth in there. The truth is that the space used by that initial number 2 (in between<br />

1 <strong>and</strong> 9,999,999,999) would remain on that index block forever. The index will not “coalesce”<br />

itself. This means if I load a table with values 1 to 500,000 <strong>and</strong> then delete every other row (all<br />

of the even numbers), there will be 250,000 “holes” in the index on that column. Only if I reinsert<br />

data that will fit onto a block where there is a hole will the space be reused. <strong>Oracle</strong> will<br />

make no attempt to “shrink” or compact the index. This can be done via an ALTER INDEX<br />

REBUILD or COALESCE comm<strong>and</strong>. On the other h<strong>and</strong>, if I load a table with values 1 to 500,000<br />

<strong>and</strong> then delete from the table every row where the value was 250,000 or less, I would find the<br />

blocks that were cleaned out of the index were put back onto the freelist for the index. This<br />

space can be totally reused.<br />

If you recall, this was the second myth: index space is never “reclaimed.” It states that<br />

once an index block is used, it will be stuck in that place in the index structure forever <strong>and</strong> will<br />

only be reused if you insert data that would go into that place in the index anyway. We can<br />

show that this is false as well. First, we need to build a table with about 500,000 rows in it. For<br />

that, we’ll use the big_table script. After we have that table with its corresponding primary key<br />

index, we’ll measure how many leaf blocks are in the index <strong>and</strong> how many blocks are on the<br />

freelist for the index. Remember, with an index, a block will only be on the freelist if the block<br />

is entirely empty, unlike a table. So any blocks we see on the freelist are completely empty <strong>and</strong><br />

available for reuse:<br />

ops$tkyte@ORA10GR1> select count(*) from big_table;<br />

COUNT(*)<br />

----------<br />

500000<br />

ops$tkyte@ORA10GR1> declare<br />

2 l_freelist_blocks number;<br />

3 begin<br />

4 dbms_space.free_blocks<br />

5 ( segment_owner => user,<br />

6 segment_name => 'BIG_TABLE_PK',<br />

7 segment_type => 'INDEX',<br />

8 freelist_group_id => 0,<br />

9 free_blks => l_freelist_blocks );<br />

10 dbms_output.put_line( 'blocks on freelist = ' || l_freelist_blocks );<br />

11 end;

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

Saved successfully!

Ooh no, something went wrong!