Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Karthick.

Asked: February 27, 2008 - 4:16 am UTC

Last updated: February 28, 2008 - 11:18 pm UTC

Version: 10g

Viewed 1000+ times

You Asked

This question is specific to B Tree index.

Following are the type of index scans I know

1. Index Unique Scan
This happens on a unique index and when we need to pick single record. And this happens when ever there is a "=" operation in the where clause.

2. Index Range Scan
This happens when we select a range of records. By giving > or < like that.

3. Index fast full scan
This happen when oracle does not have to go to the table to fetch the data and all the required information is available in the index itself.

This is what all I know about this in a brief.

But what I would like to know is how the scanning happens for all the above three in a b tree index. Dose the traversing happens the same way for all the type of scan or there is any difference. Can you give an example and explain how its scans through the index. I searched for this and couldn¿t find much.

And also can you throw some light on index rebuild. I have been hearing for some time now these two controversial statements.

1. Index rebuild will improve performance.
2. Statement 1 is just a myth.

A reference from this site http://www.miracleas.dk/images/upload/Docs/Richard%20Foote.pdf
Says B Tree index is always balanced. But I can¿t make much out of the examples. Can you let me know how can I identify that my index is balanced and how may levels are there in that index.

Than you.

and Tom said...

1) wrong about the '='

ops$tkyte%ORA11GR1> create table t ( x int, y int );

Table created.

ops$tkyte%ORA11GR1> create unique index t_idx on t(x,y);

Index created.

ops$tkyte%ORA11GR1> exec dbms_stats.set_table_stats( user, 'T', numrows => 100000 );

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR1> @at
ops$tkyte%ORA11GR1> column PLAN_TABLE_OUTPUT format a72 truncate
ops$tkyte%ORA11GR1> set autotrace traceonly explain
ops$tkyte%ORA11GR1> select * from t where x = 5;

Execution Plan
----------------------------------------------------------
Plan hash value: 2946670127

------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time
------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |  1000 | 26000 |     2   (0)| 00:00:01
|*  1 |  INDEX RANGE SCAN| T_IDX |  1000 | 26000 |     2   (0)| 00:00:01
------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("X"=5)



2) or equals as above, or use a non-unique index in any case.

3) index range/unique/skip/join will do that too. An index fast full scan is generally used when we can avoid a full scan of the base table - yes.




If you have access to Effective Oracle by Design or Expert Oracle Database architecture, I go into index access paths in some detail.

the index SCANS use single block IO - we in general read the root block of the index, navigate to a branch block, navigate to a leaf block - and then start reading leaf blocks (they are linked together from left to right like a linked list). SCANS like this read the index "in order", in sorted key order.

the index FULL SCAN uses multi-block IO. We read N blocks at a time, we ignore root and branch blocks and just process leaf blocks (where the data is). the data is read as it exists on disk - in whatever order we hit it (the data is not read in key order)




as for the rebuild stuff - search for rebuild on this site - we've discussed this many times in the past.


a rebuild (or coalesce even better) is called for so infrequently - it is the exception to have to do that, not the rule. A rebuild/coalesce sometimes is positive, most of the time a waste of energy.


Your b*tree index is always balanced, always. So, to identify that one is balanced, you just "know it to be true".

As for the levels, you gather statistics on the index and blevel will be the height minus one (in user_indexes)

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

karthick, February 28, 2008 - 12:51 pm UTC

I guess the "=" dint go for a unique scan as the uniqueness was accomplished in t_idx with two column x,y right.

SQL> create table t ( x int, y int );

Table created.

SQL> create unique index t_idx on t(x,y);

Index created.

SQL> insert into t select level i, level j from dual connect by level <=100000;

100000 rows created.

SQL> commit;

Commit complete.

SQL> exec dbms_stats.gather_table_stats(user,'t',method_opt=> 'FOR ALL INDEXED COLUMNS');

PL/SQL procedure successfully completed.

SQL> column PLAN_TABLE_OUTPUT format a72 truncate

SQL> set autotrace traceonly explain

SQL> select * from t where x = 5;

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=9)
   1    0   INDEX (RANGE SCAN) OF 'T_IDX' (INDEX (UNIQUE)) (Cost=2 Card=1 Bytes=9)

SQL> select * from t where x = 5 and y = 5;

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=1 Bytes=9)
   1    0   INDEX (UNIQUE SCAN) OF 'T_IDX' (INDEX (UNIQUE)) (Cost=1 Card=1 Bytes=9)

Tom Kyte
February 28, 2008 - 11:18 pm UTC

anytime you have a concatenated index (an index on more than one attribute), using "=" on less than ALL indexed attributes will have to range scan.

"=" on a unique index does not imply in general that a unique scan will be done. that is all.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library