Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.misc -> Re: Why would an index not be used if specified as a hint in a query?
"DA Morgan" <damorgan_at_x.washington.edu> wrote in message
news:1108235973.485860_at_yasure...
> Niall Litchfield wrote:
>
>> "DA Morgan" <damorgan_at_x.washington.edu> wrote in message
>> news:1108185875.191030_at_yasure...
>>
>>>Craig & Co. wrote:
>>>
>>>
>>>>Hi,
>>>>
>>>>Running Oracle 8.1.7.4 on Solaris 2.8.
>>>>
>>>>Running explain plan, and then a query (I don't have a copy to show at
>>>>this
>>>>point), apparently
>>>>the index is not used.
>>>>
>>>>I assume it is because the optimiser thinks the index is not required
>>>>even
>>>>though it is specified.
>>>>
>>>>Cheers
>>>>Craig.
>>>
>>>A reasonable presumption.
>>>
>>>On the other hand it could be lack of statistics for the optimizer or
>>>any one of a number of things. Small matters like the number of rows
>>>in the table, the applicability of the index to the query, the
>>>cardinality, and the percentage of rows to be returned could also be
>>>affecting the outcome.
>>
>>
>> A reasonable presumption indeed, but an incorrect one - assuming I
>> understand 'not required' correctly - equally only one of your factors
>> should be relevant.
>>
>> Using an INDEX hint *WILL* cause the index to be used *IF IT CAN BE*
>
> Let's not turn into a testosterone contest but the OP wrote: "... the
> index is not required even though it is specified." which indicates to me
> that a hint was tried. Otherwise how could you "specify" an index?
I too assumed that we were talking about hints. Unfortunately I pressed send instead of save as draft when my daughter came to suggest that it was breakfast time not computer time. Thus you got a half finished all capitalized post that doesn't explain anything. Not my finest hour.
It was the word 'required' that got me wondering. I read the original question (like your comments about cardinality etc) as meaning that Oracle had decided to 'ignore' the hint and use a different path. Oracle won't ignore valid, syntactically correct hints (otherwise really what would be the point of them?)
So reasons that Oracle might choose to not use a specified index
> Assuming, thereupon, that the index hint was used and ignored by Oracle,
> it may be that the index was not appropriate for the query ... for
> example an incorrect column order ... it may be that the OP's query was
> for 85% of the rows in the table ... or, I think, the other items I
> mentioned. If under those conditions they are incorrect I'd appreciate
> knowing why.
The other items that you mentioned, the proportion of rows (or rather blocks) expected by the optimiser to be visited to satisfy the query for example, are excellent reasons for the CBO not to use an index in the absence of a hint - i.e. there is a plan that looks as if it will do less work than the indexed access path. If there is a valid index hint though you are telling the optimizer to use that index if at all possible and regardless of cost. It will therefore use it if it can.
> But given that we've not seen the SQL, not seen the explain plan, and
> not seen the DDL for the table or index(es) I'd say we were both
> shooting in the dark. I would, though, like to know why my statements
> would be incorrect if, as I did, it is assumed a hint was used.
I cannot offer reasons why the index isn't used in this particular case, but in general it will either be that the hint is invalid or the index cannot actually be used to satisfy the query. As it happens we had a very similar question almost exactly 2 years ago http://tinyurl.com/55rgo is the reference.
I do have a little example I just cooked up on nullability, in this case the index would be chosen by the CBO if it could be used, however it would be quite common in the initial stages to wonder why my index on owner was being ignored and to try hinting it.
SQL> conn /
Connected.
SQL> create table t1 as select * from all_objects;
Table created.
SQL> desc t1;
Name Null? Type ----------------------------------------- -------- ---------------------------- OWNER VARCHAR2(30) OBJECT_NAME VARCHAR2(30) SUBOBJECT_NAME VARCHAR2(30) OBJECT_ID NUMBER DATA_OBJECT_ID NUMBER OBJECT_TYPE VARCHAR2(19) CREATED DATE LAST_DDL_TIME DATE TIMESTAMP VARCHAR2(19) STATUS VARCHAR2(7) TEMPORARY VARCHAR2(1) GENERATED VARCHAR2(1) SECONDARY VARCHAR2(1)
SQL> create index idx1
2 on t1(owner);
Index created.
SQL> exec dbms_stats.gather_table_stats(user,'T1',cascade=>
true,estimate_percen
t=>10);
PL/SQL procedure successfully completed.
SQL> explain plan
2 for
3 select owner,count(*)
4 from t1
5 group by owner;
Explained.
SQL> set lines 120
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 21 | 126 | 153 (4)| 00:00:02 | | 1 | SORT GROUP BY | | 21 | 126 | 153 (4)| 00:00:02 | | 2 | TABLE ACCESS FULL| T1 | 47940 | 280K| 149 (1)| 00:00:02 | ---------------------------------------------------------------------------
9 rows selected.
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 21 | 126 | 153 (4)| 00:00:02 | | 1 | SORT GROUP BY | | 21 | 126 | 153 (4)| 00:00:02 | | 2 | TABLE ACCESS FULL| T1 | 47940 | 280K| 149 (1)| 00:00:02 | ---------------------------------------------------------------------------
9 rows selected.
SQL> alter table t1
2 modify owner not null;
Table altered.
SQL> explain plan
2 for
3 select /*+ INDEX(T1 IDX1) */ owner,count(*)
4 from t1
5 group by owner;
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 21 | 126 | 112 (1)| 00:00:02 | | 1 | SORT GROUP BY NOSORT| | 21 | 126 | 112 (1)| 00:00:02 | | 2 | INDEX FULL SCAN | IDX1 | 47940 | 280K| 112 (1)| 00:00:02 | -----------------------------------------------------------------------------
9 rows selected.
SQL> explain plan
2 for
3 select object_name from t1
4 WHERE OWNER IN ('SYS','SYSTEM','CTXSYS');
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
Plan hash value: 1931397137
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter("OWNER"='CTXSYS' OR "OWNER"='SYS' OR "OWNER"='SYSTEM')
13 rows selected.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
Plan hash value: 1931397137
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter("OWNER"='CTXSYS' OR "OWNER"='SYS' OR "OWNER"='SYSTEM')
13 rows selected.
SQL> EXPLAIN PLAN
2 FOR
3 SELECT /*+ INDEX(T1 IDX1) */ OBJECT_NAME FROM T1
4 WHERE OWNER IN ('SYS','SYSTEM','CTXSYS');
Explained.
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6256 | 189K| 181 (0)| 00:00:03 | | 1 | INLIST ITERATOR | | | | ||
PLAN_TABLE_OUTPUT
3 - access("OWNER"='CTXSYS' OR "OWNER"='SYS' OR "OWNER"='SYSTEM')
15 rows selected.
SQL>
-- Niall Litchfield Oracle DBA http://www.niall.litchfield.dial.pipex.comReceived on Sat Feb 12 2005 - 15:14:02 CST