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

When Should You Use a B*Tree Index?<br />

Not being a big believer in “rules of thumb” (there are exceptions to every rule), I don’t have<br />

any rules of thumb for when to use (or not to use) a B*Tree index. To demonstrate why I don’t<br />

have any rules of thumb for this case, I’ll present two equally valid ones:<br />

• Only use B*Tree to index columns if you are going to access a very small percentage of<br />

the rows in the table via the index.<br />

• Use a B*Tree index if you are going to process many rows of a table <strong>and</strong> the index can be<br />

used instead of the table.<br />

These rules seem to offer conflicting advice, but in reality, they do not—they just cover<br />

two extremely different cases. There are two ways to use an index given the preceding advice:<br />

• As the means to access rows in a table: You will read the index to get to a row in the table.<br />

Here you want to access a very small percentage of the rows in the table.<br />

• As the means to answer a query: The index contains enough information to answer<br />

the entire query—we will not have to go to the table at all. The index will be used as a<br />

“thinner” version of the table.<br />

There are other ways as well—for example, we could be using an index to retrieve all of<br />

the rows in a table, including columns that are not in the index itself. That seemingly goes<br />

counter to both rules of thumb just presented. The case that would be true would be an interactive<br />

application where you are getting some of the rows <strong>and</strong> displaying them, then some<br />

more, <strong>and</strong> so on. You want to have the query optimized for initial response time, not overall<br />

throughput.<br />

The first case (i.e., use the index if you are going to access a small percentage of the table)<br />

says if you have a table T (using the same table T from earlier) <strong>and</strong> you have a query plan that<br />

looks like this:<br />

ops$tkyte@ORA10G> set autotrace traceonly explain<br />

ops$tkyte@ORA10G> select owner, status<br />

2 from t<br />

3 where owner = USER;<br />

Execution Plan<br />

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

0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=1947 Bytes=25311)<br />

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE) (Cost=3 Card=1947 ....<br />

2 1 INDEX (RANGE SCAN) OF 'DESC_T_IDX' (INDEX) (Cost=2 Card=8)<br />

then you should be accessing a very small percentage of this table. The issue to look at here is<br />

the INDEX (RANGE SCAN) followed by the TABLE ACCESS BY INDEX ROWID. This means that <strong>Oracle</strong><br />

will read the index <strong>and</strong> then, for the index entries, it will perform a database block read (logical<br />

or physical I/O) to get the row data. This is not the most efficient method if you are going<br />

to have to access a large percentage of the rows in T via the index (shortly we will define what<br />

a large percentage might be).

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

Saved successfully!

Ooh no, something went wrong!