A new form of index hint appeared in 10g – and it’s becoming more common to see it in production code; instead of naming indexes in index hints, we describe them. Consider the following hint (expressed in two ways, first as it appeared in the outline section of an execution plan, then cosmetically adjusted to look more like the way you would write it in your SQL):
INDEX(@"SEL$1" "PRD"@"SEL$1" ("PRODUCTS"."PRODUCT_GROUP" "PRODUCTS"."ID")) index(@sel$1 prd@sel$1(product_group id))
With this syntax, Oracle is directed to use an index on the table aliased as prd in query block with the (default) name sel$1; the index has to start with the columns (product_group, id) in that order – with preference given to an exact match, otherwise using the lowest cost index that starts the right way. In passing, although this example shows the default query block names, it’s good practice to name query blocks explicitly with the /*+ qb_name() */ hint.
With this in mind, what is the correct way to hint an index with the following definition:
create index prd_case on products( case product_group when 'CLASSICAL CD' then id end ) ;
The correct answer is the obvious guess – you have to go back to the old syntax which (again in two versions) would be:
INDEX(@"SEL$1" "PRD"@"SEL$1" "PRD_CASE") index(@sel$1 prd@sel$1 prd_case)
There simply is no alternative.
So how about hinting a bitmap join index, e.g:
create bitmap index pe_home_st_idx on people(st.name) from states st, towns ho, people pe where ho.id_state = st.id and pe.id_town_home = ho.id ;
Again you could use the traditional approach of supplying the index name, but in this case you can also take the newer approach of supplying the index description – except you have to remember to qualify any column names with their table name (irrespective of the aliases you used for the table in the query) e.g:
/*+ index(pe (states.name)) */
Finally, left as an exercise to the readers, how should you hint an index on a virtual column:
alter table products add cd_product generated always as ( case product_group when 'CLASSICAL CD' then id end ) virtual ; create index prd_virt on products(cd_product);
If you check user_tab_columns and user_ind_columns they both contain the column name cd_product, so it seems pretty clear that we should be able to use the 10g description method – but will the optimizer recognise the index if hinted that way, and what will the outline section of the execution plan show ?
From the outline data, the old methed is used: index_rs_asc(@sel$1,production_information@sel$1,prd_virt)
I guess because the index type is function-base
Comment by Sid — November 24, 2011 @ 3:21 pm GMT Nov 24,2011 |
“There simply is no alternative.”
There is no (sensible) alternative.
i.e. could you not use the hidden column name?
Comment by Dom Brooks — November 24, 2011 @ 4:43 pm GMT Nov 24,2011 |
I just realised that whilst going off and exploring the points you were making, I wandered away from the FBI you had with a CASE and it’s possible that my FBI with NVL may be different in some way to an expression with case….
Comment by Dom Brooks — November 25, 2011 @ 8:23 am GMT Nov 25,2011 |
As expected it was the same.
Of course the danger of the hidden column name is that it might not be the same from environment to environment. So definitely not a sensible approach.
Comment by Dom Brooks — November 25, 2011 @ 9:15 am GMT Nov 25,2011 |
Dom,
Nice comment, especially the addition of (sensible).
Thanks for that – and the follow-up.
Interestingly the same strategy fails (in 10.2.0.3) for my bitmap join index example, although it worked for a bitmap join index which was a two-table join rather than three tables
Your example did make me think about the side effects of things like export/import, and dropping indexes, etc.
I hope everyone noticed your comment about danger – here’s a little threat waitng to happen if anyone takes that approach in production:
Notice how the virtual column for index pe_ho2 starts life as sys_nc00005$, but changes to sys_nc00004$ when you drop the index pe_ho1 ?
That surprised me – I thought I’d have to use an export import pass to switch virtual columes on the indexes
Comment by Jonathan Lewis — November 25, 2011 @ 10:05 am GMT Nov 25,2011 |
Indeed – definitely surprising.
Comment by Dom Brooks — November 25, 2011 @ 10:41 am GMT Nov 25,2011 |
[…] a little history recently I came across a note I’d written about the new-style index hint. In that note I claimed that: … the index has to start with the columns (product_group, id) […]
Pingback by Quiz Night « Oracle Scratchpad — January 13, 2012 @ 6:42 pm GMT Jan 13,2012 |
Hi Jonathan,
Which views do we need to query to find the the current running queries which are using indexes with high costs? Kindly suggest.
Thanks,
Kartik
Comment by kartik — April 5, 2012 @ 7:13 am BST Apr 5,2012 |
[…] New Index hints (Nov 2011): Oracle 10g introduced an index hinting by description. Some examples and comments. […]
Pingback by Indexing Catalogue | Oracle Scratchpad — July 15, 2022 @ 7:46 pm BST Jul 15,2022 |
[…] New Index hints (Nov 2011): Oracle 10g introduced an index hinting by description. Some examples and comments. […]
Pingback by Hinting Catalogue | Oracle Scratchpad — July 15, 2022 @ 7:52 pm BST Jul 15,2022 |