Managing Indexes

Indexes are optional structures associated with tables. You can create them to improve query performance. Just as the index in this book helps you to quickly locate specific information, an Oracle Database index provides a quick access path to table data.

You can create indexes on one or more columns of a table. After an index is created, it is automatically maintained and used by Oracle Database. Changes to a table's data or structure, such as adding new rows, updating rows, or deleting rows, are automatically incorporated into all relevant indexes with complete transparency to the user.

Some indexes are created implicitly through constraints that are placed on a table. For example, a column with the constraint that its values be unique causes Oracle Database to create a unique key index.

Oracle Database automatically creates the indexes necessary to support data integrity defined with constraints when you add or enable those constraints. For performance purposes, you might want to add an index to the columns you define in a child table when adding a foreign key constraint. Before you add additional indexes, you should examine the performance of your database. You can then compare performance after the new indexes are added.

After index creation, Oracle Database automatically synchronizes the index with any subsequent inserts, updates, or deletes to the base table.

Indexes are generally of value to queries and to SQL statements that need to operate on a single, existing row or a small number of existing rows. Too many indexes can cause serious problems by increasing the processing overhead for statements that add, modify, or delete rows. In some cases, a statement could use two or more indexes and the optimizer picks just one of them. Unless other statements can take advantage of the unused indexes, they are not providing any benefit. Therefore, you might find yourself deleting indexes if you create too many.

This topic contains the following topics:

Creating Indexes for Use with Constraints

All enabled unique and primary keys require corresponding indexes, although in most cases the indexes are created automatically. Note the following:

You should almost always index foreign keys; the database does not do this for you automatically.

Index Types

Indexes can be categorized in a number of ways. The primary options are:

Normal

A standard, B-tree index contains an entry for each value in the index key along with an address to the row where the value is stored. A B-tree index is the default and most common type of index in an Oracle database.

Ascending and Descending

The default search through an index is from lowest to highest value, where character data is sorted by ASCII values, numeric data from smallest to largest number, and date from the earliest to the latest value. This default behavior is performed in indexes created as ascending indexes. You can cause index searches to reverse the search order by creating the related index with the descending option.

Column and Function-based

Typically, an index entry is based on the value or values found in the table's column or columns. This is a column index. Alternatively, you can create a function-based index in which the indexed value is derived from the table data. For example, to find character data that can be in mixed case, you could use a function-based index to look for the values as if they were all in uppercase characters.

Single Column and Concatenated

You can create an index on just one column, which is called a single column index, or on multiple columns, which is called a concatenated index. Concatenated indexes are useful when all of the columns are likely to be included in the WHERE clause of frequently executed SQL statements.

For concatenated indexes, you should define the columns used in the index carefully so that the column with the fewest duplicate values is named first, the column with next fewest duplicate values is second, and so on. Columns with many duplicate values or many rows with NULL values should not be included or should be the last-named columns in the index definition.

Guidelines for Creating Indexes

You can create indexes on columns to speed up queries. Indexes provide faster access to data for operations that return a small portion of a table's rows.

In general, you should create an index on a column in any of the following situations:

You can create an index on any column; however, if the column is not used in any of these situations, creating an index on the column does not increase performance and the index takes up resources unnecessarily.

Although the database creates an index for you on a column with an integrity constraint, explicitly creating an index on such a column is recommended.

Index the Correct Tables and Columns

Use the following guidelines for determining when to create an index:

  • Create an index if you frequently want to retrieve less than about 15% of the rows in a large table. This threshold percentage varies greatly, however, according to the relative speed of a table scan and how clustered the row data is about the index key. The faster the table scan, the lower the percentage; the more clustered the row data, the higher the percentage.

  • Index columns that are used for joins to improve join performance.

  • Primary and unique keys automatically have indexes, but you might want to create an index on a foreign key. See "Foreign Key" for more information.

  • Small tables do not require indexes; if a query is taking too long, then the table might have grown from small to large.

Some columns are strong candidates for indexing. Columns with one or more of the following characteristics are good candidates for indexing:

  • Values are unique in the column, or there are few duplicates.

  • There is a wide range of values (good for regular indexes).

  • The column contains many nulls, but queries often select all rows having a value. In this case, a comparison that matches all the non-null values, such as:

    WHERE COL_X >= -9.99 *power(10,125)

    is preferable to

    WHERE COL_X IS NOT NULL

    This is because the first uses an index on COL_X (assuming that COL_X is a numeric column).

Columns with the following characteristics are less suitable for indexing:

  • There are many nulls in the column and you do not search on the non-null values.

The size of a single index entry cannot exceed roughly one-half (minus some overhead) of the available space in the data block. Consult with the database administrator for assistance in determining the space required by an index.

Limit the Number of Indexes for Each Table

The more indexes, the more overhead is incurred as the table is altered. When rows are inserted or deleted, all indexes on the table must be updated. When a column is updated, all indexes on the column must be updated.

You must weigh the performance benefit of indexes for queries against the performance overhead of updates. For example, if a table is primarily read-only, you might use more indexes; but, if a table is heavily updated, you might use fewer indexes.

Choose the Order of Columns in Composite Indexes

Although you can specify columns in any order in the CREATE INDEX command, the order of columns in the CREATE INDEX statement can affect query performance. In general, you should put the column expected to be used most often first in the index. You can create a composite index (using several columns), and the same index can be used for queries that reference all of these columns, or just some of them.

For example, assume the columns of the vendor_parts table are as follows:


vendor_id    part_no    unit_cost
1010         10-440          0.27
1010         10-457          5.10
1012         08-300          1.19
1012         10-440          0.25
1012         10-441          0.39
1012         10-457          4.96
1220         08-300          1.33
1292         10-457          5.29

Assume that there are five vendors, and each vendor has about 1000 parts. Suppose that the vendor_parts table is commonly queried by SQL statements such as the following:


SELECT * FROM vendor_parts
    WHERE part_no = 457 AND vendor_id = 1012;

To increase the performance of such queries, you might create a composite index putting the most selective column first; that is, the column with the most values:

CREATE INDEX ind_vendor_id ON vendor_parts (part_no, vendor_id);

Composite indexes speed up queries that use the leading portion of the index. So in this example, queries with WHERE clauses using only the part_no column also note a performance gain. Because there are only five distinct values, placing a separate index on vendor_id would serve no purpose.

Drop Indexes That Are No Longer Required

You might drop an index if:

  • It does not speed up queries. The table might be very small, or there might be many rows in the table but very few index entries.

  • The queries in your applications do not use the index.

  • The index must be dropped before being rebuilt.

You cannot drop an index which is created through a constraint. You must drop the constraint and then the index is dropped also.

If you drop a table, then all associated indexes are dropped.

To drop an index, the index must be contained in your schema or you must have the DROP ANY INDEX system privilege.