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.

474<br />

CHAPTER 11 ■ INDEXES<br />

Now that you know how a B*Tree will treat null values, you can use that to your advantage<br />

<strong>and</strong> take precautions with unique constraints on sets of columns that all allow nulls (be prepared<br />

to have more than one row that is all null as a possibility in this case).<br />

Should Foreign Keys Be Indexed?<br />

The question of whether or not foreign keys should be indexed comes up frequently. We<br />

touched on this subject in Chapter 6 when discussing deadlocks. There, I pointed out that<br />

unindexed foreign keys are the biggest single cause of deadlocks that I encounter, due to the<br />

fact that an update to a parent table’s primary key or the removal of a parent record will place<br />

a table lock on the child table (no modifications to the child table will be allowed until the<br />

statement completes). This locks many more rows than it should <strong>and</strong> decreases concurrency.<br />

I see it frequently when people are using a tool that generates the SQL to modify a table. The<br />

tool generates an updates that updates every column in the table, regardless of whether or not<br />

the value was UPDATE statement modified. This in effect updates the primary key (even though<br />

they never changed the value). For example, <strong>Oracle</strong> Forms will do this by default, unless you<br />

tell it to just send modified columns over to the database. In addition to the table lock issue<br />

that might hit you, an unindexed foreign key is bad in the following cases as well:<br />

• When you have an ON DELETE CASCADE <strong>and</strong> have not indexed the child table. For example,<br />

EMP is child of DEPT. DELETE FROM DEPT WHERE DEPTNO = 10 should cascade to EMP. If DEPTNO<br />

in EMP is not indexed, you will get a full table scan of EMP. This full scan is probably<br />

undesirable, <strong>and</strong> if you delete many rows from the parent table, the child table will be<br />

scanned once for each parent row deleted.<br />

• When you query from the parent to the child. Consider the EMP/DEPT example again. It is<br />

very common to query the EMP table in the context of a DEPTNO. If you frequently query<br />

select *<br />

from dept, emp<br />

where emp.deptno = dept.deptno<br />

<strong>and</strong> dept.dname = :X;<br />

to generate a report or something, you’ll find not having the index in place will slow<br />

down the queries. This is the same argument I gave for indexing the NESTED_COLUMN_ID<br />

of a nested table in Chapter 10. The hidden NESTED_COLUMN_ID of a nested table is nothing<br />

more than a foreign key.<br />

So, when do you not need to index a foreign key? In general, when the following conditions<br />

are met:<br />

• You do not delete from the parent table.<br />

• You do not update the parent table’s unique/primary key value, either purposely or by<br />

accident (via a tool).<br />

• You do not join from the parent table to the child table, or more generally the foreign<br />

key columns do not support an important access path to the child table <strong>and</strong> you do not<br />

use them in predicates to select data from this table (such as DEPT to EMP).

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

Saved successfully!

Ooh no, something went wrong!