You can create indexes on functions and expressions that involve one or more columns in the table being indexed. A function-based index computes the value of a function or expression involving one or more columns and stores it in the index. A function-based index can be either a B-tree or a bitmap index.
The function used for building the index can be an arithmetic expression or an expression that contains a SQL function, user-defined PL/SQL function, package function, or C callout. For example, a function could add the values in two columns.
Function-based indexes are efficient for evaluating statements that contain functions in their WHERE clauses. The database only uses the function-based index when the function is included in a query. When the database processes INSERT and UPDATE statements, however, it must still evaluate the function to process the statement.
For example, suppose you create the following function-based index:
CREATE INDEX emp_total_sal_idx ON employees (12 * salary * commission_pct, salary, commission_pct);
The database can use the preceding index when processing queries such as Example 3-6 (partial sample output included).
SELECT employee_id, last_name, first_name, 12*salary*commission_pct AS "ANNUAL SAL" FROM employees WHERE (12 * salary * commission_pct) < 30000 ORDER BY "ANNUAL SAL" DESC; EMPLOYEE_ID LAST_NAME FIRST_NAME ANNUAL SAL ----------- ------------------------- -------------------- ---------- 159 Smith Lindsey 28800 151 Bernstein David 28500 152 Hall Peter 27000 160 Doran Louise 27000 175 Hutton Alyssa 26400 149 Zlotkey Eleni 25200 169 Bloom Harrison 24000
Function-based indexes defined on the SQL functions UPPER(column_name) or LOWER(column_name) facilitate case-insensitive searches. For example, suppose that the first_name column in employees contains mixed-case characters. You create the following function-based index on the hr.employees table:
CREATE INDEX emp_fname_uppercase_idx ON employees ( UPPER(first_name) );
The emp_fname_uppercase_idx index can facilitate queries such as the following:
SELECT * FROM employees WHERE UPPER(first_name) = 'AUDREY';
A function-based index is also useful for indexing only specific rows in a table. For example, the cust_valid column in the sh.customers table has either I or A as a value. To index only the A rows, you could write a function that returns a null value for any rows other than the A rows. You could create the index as follows:
CREATE INDEX cust_valid_idx ON customers ( CASE cust_valid WHEN 'A' THEN 'A' END );
The optimizer can use an index range scan on a function-based index for queries with expressions in WHERE clause. The range scan access path is especially beneficial when the predicate is highly selective, that is, when it chooses relatively few rows. In Example 3-6 the optimizer can use an index range scan if an index is built on the expression 12*salary*commission_pct.
A virtual column is useful for speeding access to data derived from expressions. For example, you could define virtual column annual_sal as 12*salary*commission_pct and create a function-based index on annual_sal.
The optimizer performs expression matching by parsing the expression in a SQL statement and then comparing the expression trees of the statement and the function-based index. This comparison is case-insensitive and ignores blank spaces.
Overview of Application Domain Indexes >>