05.11.2015 Views

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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 1 ■ DEVELOPING SUCCESSFUL ORACLE APPLICATIONS 7<br />

that they wanted to index that column. They had read somewhere that bitmap indexes are<br />

for low-cardinality columns (columns that have only a few distinct values) so it seemed a natural<br />

fit.<br />

Nevertheless, that bitmap index was the cause of all of their problems. In a bitmap index,<br />

a single key entry points to many rows—hundreds or more of them. If you update a bitmap<br />

index key, the hundreds of records to which that key points are effectively locked as well as the<br />

single row you are actually updating.<br />

So, someone inserting a new N record would lock an N key in the bitmap index, effectively<br />

locking hundreds of other N records as well. Meanwhile, the process trying to read this<br />

table <strong>and</strong> process the records would be prevented from modifying some N record to be a<br />

Y (processed) record, because in order for it to update this column from N to Y, it would need<br />

to lock that same bitmap index key. In fact, other sessions just trying to insert a new record<br />

into this table would be blocked as well, as they would be attempting to lock this same bitmap<br />

key entry. In short, the developers had implemented a set of structures that at most one person<br />

would be able to insert or update against at a time!<br />

I can demonstrate this scenario easily with a simple example. Here, I use two sessions to<br />

demonstrate the blocking that can easily happen:<br />

ops$tkyte@ORA10G> create table t ( processed_flag varchar2(1) );<br />

Table created.<br />

ops$tkyte@ORA10G> create bitmap index t_idx on t(processed_flag);<br />

Index created.<br />

ops$tkyte@ORA10G> insert into t values ( 'N' );<br />

1 row created.<br />

Now, in another SQL*Plus session, if I execute<br />

ops$tkyte@ORA10G> insert into t values ( 'N' );<br />

that statement will “hang” until I issue a COMMIT in the first blocking session.<br />

So here we had an issue whereby a lack of underst<strong>and</strong>ing of the database feature (bitmap<br />

indexes), of what it did <strong>and</strong> how it worked, meant that the database was doomed to poor scalability<br />

from the start. Once this issue was discovered, correcting it was easy. We needed an index<br />

on the processed flag column, but not a bitmap index. We needed a conventional B*Tree<br />

index here. This took a bit of convincing because no one wanted to believe that use of a conventional<br />

index on a column with two distinct values was a “good idea.” But after setting up a<br />

simulation (I am very much into simulations, testing, <strong>and</strong> experimenting), we were able to<br />

prove that it was the correct approach. There were two ways to approach the indexing of this<br />

particular column:<br />

• Just create an index on the processed flag column.<br />

• Create an index only on the processed flag column when the processed flag is N—that<br />

is, only index the values of interest. Typically, we do not want to use an index where the<br />

processed flag is Y, since the vast majority of the records in the table would have the<br />

value Y. Notice that I did not say “We never want to use”—if you need to frequently<br />

count the number of processed records for some reason, then an index on the<br />

processed records may well prove useful.

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

Saved successfully!

Ooh no, something went wrong!