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 475<br />

If you satisfy all three criteria, feel free to skip the index—it is not needed <strong>and</strong> will slow<br />

down DML on the child table. If you do any of the three, be aware of the consequences.<br />

As a side note, if you believe that a child table is getting locked via an unindexed foreign<br />

key <strong>and</strong> you would like to prove it (or just prevent it in general), you can issue the following:<br />

ALTER TABLE DISABLE TABLE LOCK;<br />

Now, any UPDATE or DELETE to the parent table that would cause the table lock will receive<br />

ERROR at line 1:<br />

ORA-00069: cannot acquire lock -- table locks disabled for <br />

This is useful in tracking down the piece of code that is doing what you believe should not<br />

be done (no UPDATEs or DELETEs of the parent primary key), as the end users will immediately<br />

report this error back to you.<br />

Why Isn’t My Index Getting Used?<br />

There are many possible causes of this. In this section, we’ll take a look at some of the most<br />

common.<br />

Case 1<br />

We’re using a B*Tree index, <strong>and</strong> our predicate does not use the leading edge of an index. In this<br />

case, we might have a table T with an index on T(x,y). We query SELECT * FROM T WHERE Y = 5.<br />

The optimizer will tend not to use the index since our predicate did not involve the column<br />

X—it might have to inspect each <strong>and</strong> every index entry in this case (we’ll discuss an index skip<br />

scan shortly where this is not true). It will typically opt for a full table scan of T instead. That<br />

does not preclude the index from being used. If the query was SELECT X,Y FROM T WHERE Y = 5,<br />

the optimizer would notice that it did not have to go to the table to get either X or Y (they are in<br />

the index) <strong>and</strong> may very well opt for a fast full scan of the index itself, as the index is typically<br />

much smaller than the underlying table. Note also that this access path is only available with<br />

the CBO.<br />

There is another case whereby the index on T(x,y) could be used with the CBO is during<br />

an index skip scan. The skip scan works well if <strong>and</strong> only if the leading edge of the index (X in<br />

the previous example) has very few distinct values <strong>and</strong> the optimizer underst<strong>and</strong>s that. For<br />

example, consider an index on (GENDER, EMPNO) where GENDER has the values M <strong>and</strong> F, <strong>and</strong><br />

EMPNO is unique. A query such as<br />

select * from t where empno = 5;<br />

might consider using that index on T to satisfy the query in a skip scan method, meaning the<br />

query will be processed conceptually like this:<br />

select * from t where GENDER='M' <strong>and</strong> empno = 5<br />

UNION ALL<br />

select * from t where GENDER='F' <strong>and</strong> empno = 5;

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

Saved successfully!

Ooh no, something went wrong!