Oracle SQL Tuning with function-based indexesOracle Tips by Burleson Consulting
Oracle function-based indexes are a
super silver bullet for optimizing your SQL to do a minimum amount
of I/O to get the rows that you need.
Here are details on using
function based indexes.
Issues with function-based
One of the most common Oracle SQL tuning problems are full-table scans
that are imposed by invalidating a WHERE clause predicate with an
Oracle built-in Function (BIF). This problem is especially
prevalent when constraining SQL queries for date ranges because of the
intrinsic encryption of the relational database DATE datatype.
For example, these WHERE clause predicates might invoke an unexpected
WHERE trunc(ship_date) > trunc(sysdate-7);
WHERE to_char(ship_date,'YYYY-MM-DD') = '2004-01-04';
Even though the ship_date column may
have an index, the trunc and to_char built-in functions will
invalidate the index, causing sub-optimal execution with unnecessary
A less selective index would be
A full-table scan might be
To avoid the index invalidation
issues you have several options:
1. Fix Predicate - You can rewrite the query to leave the
ship_date predicate alone:
WHERE ship_date >= trunc(ship_date-7) + 1;
WHERE ship_date = to_date(?2004-01-04?,'YYYY-MM-DD');
2. Call FBI - Create a function-based index on the predicate:
Create index trunc_ship_date on product(trunc(ship_date));
Create index char_ship_date on product(to_char(ship_date,'YYYY-MM-DD');
3. Add Column - You could add a redundant column to the table.
This is an old Oracle7 trick that was used before the invention of
alter table product add trunc_ship_date varchar 40;
update product set trunc_ship_date = trunc(ship_date);
In sum, function-based indexes
(FBIs) are a Godsend for the Oracle DBA who has to remove unnecessary
full-table scans or fix sub-optimal index choices. Using an FBI can
positively effect all SQL statements that have the matching predicate
and speed-up an entire database.
Once an FBI is created, you need to create CBO
statistics, but beware that there are numerous bugs and issues when
analyzing a function-based index. See these important notes on
After creating a function-based index, you want
to re-gather table statistics and get extended statistics on the
Create an FBI on emp_nbr column with NULL values:
To make the function-based index work, we must now analyze the index.
Depending you your release, these methods are appropriate:
EXEC DBMS_STATS.gather_index_stats('EMP', ?emp_null_emp_nbr_idx?);
In this case, we analyze the function-based index
using the method_opt argument set to FOR ALL HIDDEN
method_opt=> ?FOR ALL HIDDEN COLUMNS
In Oracle 11g and beyond, Oracle recommends analyzing ?extended?
statistics on function-based indexes:
ownname => 'SCOTT',
tabname => 'EMP',
method_opt => 'for all columns size
skewonly for columns (nvl(ename,o))'
Also, see these related notes on
Get the Complete
Oracle SQL Tuning Information
The landmark book
SQL Tuning The Definitive Reference" is
filled with valuable information on Oracle SQL Tuning.
This book includes scripts and tools to hypercharge Oracle 11g
performance and you can
for 30% off directly from the publisher.