views:

186

answers:

5

I encountered this question in an interview and had no clue how to answer:

There is a table which has a index on a column, and you query:

select * from table_name where column_having_index="some value";

The query takes too long, and you find out that the index is not being used. If you think the performance of the query will be better using the index, how could you force the query to use the index?

+7  A: 

You can use optimizer hints

select /*+ INDEX(table_name index_name) */ from table etc...

More on using optimizer hints: http://download.oracle.com/docs/cd/B19306%5F01/server.102/b14211/hintsref.htm

Rene
Also, in more recent versions of Oracle (10g+ I think) you can specify the column name instead of the index name, e.g. `/*+INDEX(table_name column_having_index)*/`
Jeffrey Kemp
/*+INDEX(table_name (column_having_index))*/ ... opr see my answer for more complex syntax
David Aldridge
A: 

You can use:

WITH index = ...

more info

Leon
ohh.. thought you mean MS-Sql...but you get the idea :)
Leon
+1  A: 

There is an appropriate index on column_having_index, and its use actually increase performance, but Oracle didn't use it...
You should gather statistics on your table to let optimizer see that index access can help. Using direct hint is not a good practice.

egorius
Indexing hints should certainly be used sparingly but there are plenty of legitimate situations for using them. One example is where the statistics are not available to demonstrate that column values are strongly correlated, and the CBO infers an incorrect cardinality for predicates on multiple columns.
David Aldridge
David, as to the question, the example is so simple that I can't see any reason for CBO not to use index save for incorrect statistics. But in general -- you're right of course.
egorius
+5  A: 

There could be many reasons for Index not being used. Even after you specify hints, there are chances Oracle optimizer thinks otherwise and decide not to use Index. You need to go through the EXPLAIN PLAN part and see what is the cost of the statement with INDEX and without INDEX.

Assuming the Oracle uses CBO. Most often, if the optimizer thinks the cost is high with INDEX, even though you specify it in hints, the optimizer will ignore and continue for full table scan. Your first action should be checking DBA_INDEXES to know when the statistics are LAST_ANALYZED. If not analyzed, you can set table, index for analyze.

begin 
   DBMS_STATS.GATHER_INDEX_STATS ( OWNNAME=>user
                                 , INDNAME=>IndexName);
end;

For table.

begin 
   DBMS_STATS.GATHER_TABLE_STATS ( OWNNAME=>user
                                 , TABNAME=>TableName);
end;

In extreme cases, you can try setting up the statistics on your own.

Guru
The CBO will "always" honour all *correctly specified* hints - it doesn't have freedom to arbitrarily "choose" not to honour a hint.
Jeffrey Kemp
Very recently we upgraded ORA 9208 from ORA 9205, after that, we experienced this, there was a complex query, INDEX was not used. I forced it with the HINT. Even though the EXPLAIN_PLAN showed it used the INDEX, when executed it took the different path. That's when DBA suggested us to re-write the SQL. And we did that, it worked.
Guru
+2  A: 

If you think the performance of the query will be better using the index, how could you force the query to use the index?

First you would of course verify that the index gave a better result for returning the complete data set, right?

The index hint is the key here, but the more up to date way of specifying it is with the column naming method rather than the index naming method. In your case you would use:

select /*+ index(table_name (column_having_index)) */ *
from   table_name
where  column_having_index="some value";

In more complex cases you might ...

select /*+ index(t (t.column_having_index)) */ *
from   my_owner.table_name t,
       ...
where  t.column_having_index="some value";
David Aldridge