Sei sulla pagina 1di 32

By PenchalaRaju.

Yanamala

Partitioned Tables and Indexes


This chapter describes partitioned tables and indexes. It covers the following topics:

• Introduction to Partitioning
• Partitioning Methods
• Partitioned Indexes
• Partitioning to Improve Performance

Note:

Oracle supports partitioning only for tables, indexes on tables,


materialized views, and indexes on materialized views. Oracle does not
support partitioning of clustered tables or indexes on clustered tables.

Introduction to Partitioning

Partitioning addresses key issues in supporting very large tables and indexes by letting
you decompose them into smaller and more manageable pieces called partitions. SQL
queries and DML statements do not need to be modified in order to access partitioned
tables. However, after partitions are defined, DDL statements can access and
manipulate individuals partitions rather than entire tables or indexes. This is how
partitioning can simplify the manageability of large database objects. Also, partitioning is
entirely transparent to applications.

Each partition of a table or index must have the same logical attributes, such as column
names, datatypes, and constraints, but each partition can have separate physical
attributes such as pctfree, pctused, and tablespaces.

Partitioning is useful for many different types of applications, particularly applications


that manage large volumes of data. OLTP systems often benefit from improvements in
manageability and availability, while data warehousing systems benefit from
performance and manageability.

Note:

All partitions of a partitioned object must reside in tablespaces of a


single block size.

See Also:

"Multiple Block Sizes"

Oracle9i Data Warehousing Guide for more information about


partitioning

Partitioning offers these advantages:


• Partitioning enables data management operations such data loads, index
creation and rebuilding, and backup/recovery at the partition level, rather than on the
entire table. This results in significantly reduced times for these operations.
• Partitioning improves query performance. In many cases, the results of a
query can be achieved by accessing a subset of partitions, rather than the entire table.
For some queries, this technique (called partition pruning) can provide order-of-
magnitude gains in performance.
• Partitioning can significantly reduce the impact of scheduled downtime for
maintenance operations.

Partition independence for partition maintenance operations lets you perform concurrent
maintenance operations on different partitions of the same table or index. You can also
run concurrent SELECT and DML operations against partitions that are unaffected by
maintenance operations.

• Partitioning increases the availability of mission-critical databases if critical


tables and indexes are divided into partitions to reduce the maintenance windows,
recovery times, and impact of failures.
• Partitioning can be implemented without requiring any modifications to your
applications. For example, you could convert a nonpartitioned table to a partitioned
table without needing to modify any of the SELECT statements or DML statements
which access that table. You do not need to rewrite your application code to take
advantage of partitioning.

Figure 11-1 offers a graphical view of how partitioned tables differ from nonpartitioned
tables.

Figure 11-1 A View of Partitioned Tables

Text description of the illustration cncpt162.gif

Partition Key

Each row in a partitioned table is unambiguously assigned to a single partition. The


partition key is a set of one or more columns that determines the partition for each row.
Oracle9i automatically directs insert, update, and delete operations to the appropriate
partition through the use of the partition key. A partition key:

• Consists of an ordered list of 1 to 16 columns


• Cannot contain a LEVEL, ROWID, or MLSLABEL pseudocolumn or a column
of type ROWID
• Can contain columns that are NULLable

Partitioned Tables

Tables can be partitioned into up to 64,000 separate partitions. Any table can be
partitioned except those tables containing columns with LONG or LONG RAW
datatypes. You can, however, use tables containing columns with CLOB or BLOB
datatypes.

Partitioned Index-Organized Tables

You can range partition index-organized tables. This feature is very useful for providing
improved manageability, availability and performance for index-organized tables. In
addition, data cartridges that use index-organized tables can take advantage of the
ability to partition their stored data. Common examples of this are the Image and
interMedia cartridges.

For partitioning an index-organized table:

• Only range and hash partitioning are supported


• Partition columns must be a subset of primary key columns
• Secondary indexes can be partitioned -- locally and globally
• OVERFLOW data segments are always equipartitioned with the table
partitions

Partitioning Methods

Oracle provides the following partitioning methods:

• Range Partitioning
• List Partitioning
• Hash Partitioning
• Composite Partitioning

Figure 11-2 offers a graphical view of the methods of partitioning.

Figure 11-2 List, Range, and Hash Partitioning

Text description of the illustration cncpt158.gif

Composite partitioning is a combination of other partitioning methods. Oracle currently


supports range-hash and range-list composite partitioning. Figure 11-3 offers a
graphical view of range-hash and range-list composite partitioning.

Figure 11-3 Composite Partitioning

Text description of the illustration cncpt168.gif

Range Partitioning

Range partitioning maps data to partitions based on ranges of partition key values that
you establish for each partition. It is the most common type of partitioning and is often
used with dates. For example, you might want to partition sales data into monthly
partitions.

When using range partitioning, consider the following rules:

• Each partition has a VALUES LESS THAN clause, which specifies a


noninclusive upper bound for the partitions. Any binary values of the partition key equal
to or higher than this literal are added to the next higher partition.
• All partitions, except the first, have an implicit lower bound specified by the
VALUES LESS THAN clause on the previous partition.
• A MAXVALUE literal can be defined for the highest partition. MAXVALUE
represents a virtual infinite value that sorts higher than any other possible value for the
partition key, including the null value.

A typical example is given in the following section. The statement creates a table
(sales_range) that is range partitioned on the sales_date field.

Range Partitioning Example

CREATE TABLE sales_range


(salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
sales_date DATE)
PARTITION BY RANGE(sales_date)
(
PARTITION sales_jan2000 VALUES LESS
THAN(TO_DATE('02/01/2000','DD/MM/YYYY')),
PARTITION sales_feb2000 VALUES LESS
THAN(TO_DATE('03/01/2000','DD/MM/YYYY')),
PARTITION sales_mar2000 VALUES LESS
THAN(TO_DATE('04/01/2000','DD/MM/YYYY')),
PARTITION sales_apr2000 VALUES LESS
THAN(TO_DATE('05/01/2000','DD/MM/YYYY'))
);

List Partitioning

List partitioning enables you to explicitly control how rows map to partitions. You do this
by specifying a list of discrete values for the partitioning key in the description for each
partition. This is different from range partitioning, where a range of values is associated
with a partition and from hash partitioning, where a hash function controls the row-to-
partition mapping. The advantage of list partitioning is that you can group and organize
unordered and unrelated sets of data in a natural way.

The details of list partitioning can best be described with an example. In this case, let's
say you want to partition a sales table by region. That means grouping states together
according to their geographical location as in the following example.

List Partitioning Example

CREATE TABLE sales_list


(salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_state VARCHAR2(20),
sales_amount NUMBER(10),
sales_date DATE)
PARTITION BY LIST(sales_state)
(
PARTITION sales_west VALUES('California', 'Hawaii'),
PARTITION sales_east VALUES ('New York', 'Virginia', 'Florida'),
PARTITION sales_central VALUES('Texas', 'Illinois')
PARTITION sales_other VALUES(DEFAULT)
);

A row is mapped to a partition by checking whether the value of the partitioning column
for a row falls within the set of values that describes the partition. For example, the rows
are inserted as follows:

• (10, 'Jones', 'Hawaii', 100, '05-JAN-2000') maps to partition sales_west


• (21, 'Smith', 'Florida', 150, '15-JAN-2000') maps to partition sales_east
• (32, 'Lee', 'Colorado', 130, '21-JAN-2000') does not map to any partition in the
table

Unlike range and hash partitioning, multicolumn partition keys are not supported for list
partitioning. If a table is partitioned by list, the partitioning key can only consist of a
single column of the table.

The DEFAULT partition enables you to avoid specifying all possible values for a list-
partitioned table by using a default partition, so that all rows that do not map to any
other partition do not generate an error.

Hash Partitioning

Hash partitioning enables easy partitioning of data that does not lend itself to range or
list partitioning. It does this with a simple syntax and is easy to implement. It is a better
choice than range partitioning when:

• You do not know beforehand how much data maps into a given range
• The sizes of range partitions would differ quite substantially or would be
difficult to balance manually
• Range partitioning would cause the data to be undesirably clustered
• Performance features such as parallel DML, partition pruning, and partition-
wise joins are important

The concepts of splitting, dropping or merging partitions do not apply to hash partitions.
Instead, hash partitions can be added and coalesced.

Hash Partitioning Example

CREATE TABLE sales_hash


(salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
week_no NUMBER(2))
PARTITION BY HASH(salesman_id)
PARTITIONS 4
STORE IN (data1, data2, data3, data4);

The preceding statement creates a table sales_hash, which is hash partitioned on


salesman_id field. The tablespace names are data1, data2, data3, and data4.

Composite Partitioning

Composite partitioning partitions data using the range method, and within each partition,
subpartitions it using the hash or list method. Composite range-hash partitioning
provides the improved manageability of range partitioning and the data placement,
striping, and parallelism advantages of hash partitioning. Composite range-list
partitioning provides the manageability of range partitioning and the explicit control of
list partitioning for the subpartitions.

Composite partitioning supports historical operations, such as adding new range


partitions, but also provides higher degrees of parallelism for DML operations and finer
granularity of data placement through subpartitioning.

Composite Partitioning Range-Hash Example

CREATE TABLE sales_composite


(salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
sales_date DATE)
PARTITION BY RANGE(sales_date)
SUBPARTITION BY HASH(salesman_id)
SUBPARTITION TEMPLATE(
SUBPARTITION sp1 TABLESPACE data1,
SUBPARTITION sp2 TABLESPACE data2,
SUBPARTITION sp3 TABLESPACE data3,
SUBPARTITION sp4 TABLESPACE data4)
(PARTITION sales_jan2000 VALUES LESS
THAN(TO_DATE('02/01/2000','DD/MM/YYYY'))
PARTITION sales_feb2000 VALUES LESS
THAN(TO_DATE('03/01/2000','DD/MM/YYYY'))
PARTITION sales_mar2000 VALUES LESS
THAN(TO_DATE('04/01/2000','DD/MM/YYYY'))
PARTITION sales_apr2000 VALUES LESS
THAN(TO_DATE('05/01/2000','DD/MM/YYYY'))
PARTITION sales_may2000 VALUES LESS
THAN(TO_DATE('06/01/2000','DD/MM/YYYY')));

This statement creates a table sales_composite that is range partitioned on the


sales_date field and hash subpartitioned on salesman_id. When you use a template,
Oracle names the subpartitions by concatenating the partition name, an underscore,
and the subpartition name from the template. Oracle places this subpartition in the
tablespace specified in the template. In the previous statement, sales_jan2000_sp1 is
created and placed in tablespace data1 while sales_jan2000_sp4 is created and placed
in tablespace data4. In the same manner, sales_apr2000_sp1 is created and placed in
tablespace data1 while sales_apr2000_sp4 is created and placed in tablespace data4.
Figure 11-4 offers a graphical view of the previous example.

Figure 11-4 Composite Range-Hash Partitioning

Text description of the illustration cncpt157.gif

Composite Partitioning Range-List Example

CREATE TABLE bimonthly_regional_sales


(deptno NUMBER,
item_no VARCHAR2(20),
txn_date DATE,
txn_amount NUMBER,
state VARCHAR2(2))
PARTITION BY RANGE (txn_date)
SUBPARTITION BY LIST (state)
SUBPARTITION TEMPLATE(

SUBPARTITION east VALUES('NY', 'VA', 'FL') TABLESPACE ts1,


SUBPARTITION west VALUES('CA', 'OR', 'HI') TABLESPACE ts2,
SUBPARTITION central VALUES('IL', 'TX', 'MO') TABLESPACE ts3)
( PARTITION janfeb_2000 VALUES LESS THAN (TO_DATE('1-MAR-2000','DD-MON-
YYYY')), PARTITION marapr_2000 VALUES LESS THAN (TO_DATE('1-MAY-
2000','DD-MON-YYYY')), PARTITION mayjun_2000 VALUES LESS THAN
(TO_DATE('1-JUL-2000','DD-MON-YYYY')) );

This statement creates a table bimonthly_regional_sales that is range partitioned on the


txn_date field and list subpartitioned on state. When you use a template, Oracle names
the subpartitions by concatenating the partition name, an underscore, and the
subpartition name from the template. Oracle places this subpartition in the tablespace
specified in the template. In the previous statement, janfeb_2000_east is created and
placed in tablespace ts1 while janfeb_2000_central is created and placed in tablespace
ts3. In the same manner, mayjun_2000_east is placed in tablespace ts1 while
mayjun_2000_central is placed in tablespace ts3. Figure 11-5 offers a graphical view of
the table bimonthly_regional_sales and its 9 individual subpartitions.

Figure 11-5 Composite Range-List Partitioning

Text description of the illustration cncpt167.gif


When to Partition a Table

Here are some suggestions for when to partition a table:

• Tables greater than 2GB should always be considered for partitioning.


• Tables containing historical data, in which new data is added into the newest
partition. A typical example is a historical table where only the current month's data is
updatable and the other 11 months are read-only.

Partitioned Indexes

Just like partitioned tables, partitioned indexes improve manageability, availability,


performance, and scalability. They can either be partitioned independently (global
indexes) or automatically linked to a table's partitioning method (local indexes).

See Also:

Oracle9i Data Warehousing Guide for more information about


partitioned indexes

Local Partitioned Indexes

Local partitioned indexes are easier to manage than other types of partitioned indexes.
They also offer greater availability and are common in DSS environments. The reason
for this is equipartitioning: each partition of a local index is associated with exactly one
partition of the table. This enables Oracle to automatically keep the index partitions in
sync with the table partitions, and makes each table-index pair independent. Any
actions that make one partition's data invalid or unavailable only affect a single partition.

You cannot explicitly add a partition to a local index. Instead, new partitions are added
to local indexes only when you add a partition to the underlying table. Likewise, you
cannot explicitly drop a partition from a local index. Instead, local index partitions are
dropped only when you drop a partition from the underlying table.

A local index can be unique. However, in order for a local index to be unique, the
partitioning key of the table must be part of the index's key columns. Unique local
indexes are useful for OLTP environments.

Figure 11-6 offers a graphical view of local partitioned indexes.

Figure 11-6 Local Partitioned Index

Text description of the illustration cncpt161.gif

Global Partitioned Indexes

Global partitioned indexes are flexible in that the degree of partitioning and the
partitioning key are independent from the table's partitioning method. They are
commonly used for OLTP environments and offer efficient access to any individual
record.

The highest partition of a global index must have a partition bound, all of whose values
are MAXVALUE. This ensures that all rows in the underlying table can be represented
in the index. Global prefixed indexes can be unique or nonunique.

You cannot add a partition to a global index because the highest partition always has a
partition bound of MAXVALUE. If you wish to add a new highest partition, use the
ALTER INDEX SPLIT PARTITION statement. If a global index partition is empty, you
can explicitly drop it by issuing the ALTER INDEX DROP PARTITION statement. If a
global index partition contains data, dropping the partition causes the next highest
partition to be marked unusable. You cannot drop the highest partition in a global index.

Maintenance of Global Partitioned Indexes

By default, the following operations on partitions on a heap-organized table mark all


global indexes as unusable:

ADD (HASH)
COALESCE (HASH)
DROP
EXCHANGE
MERGE
MOVE
SPLIT
TRUNCATE

These indexes can be maintained by appending the clause UPDATE GLOBAL


INDEXES to the SQL statements for the operation. The two advantages to maintaining
global indexes:

• The index remains available and online throughout the operation. Hence no
other applications are affected by this operation.
• The index doesn't have to be rebuilt after the operation.

Example:

ALTER TABLE DROP PARTITION P1 UPDATE GLOBAL INDEXES

Note:

This feature is supported only for heap organized tables.

See Also:

Oracle9i SQL Reference for more information about the UPDATE


GLOBAL INDEX clause

Figure 11-7 offers a graphical view of global partitioned indexes.


Figure 11-7 Global Partitioned Index

Text description of the illustration cncpt160.gif

Global Nonpartitioned Indexes

Global nonpartitioned indexes behave just like a nonpartitioned index. They are
commonly used in OLTP environments and offer efficient access to any individual
record.

Figure 11-8 offers a graphical view of global nonpartitioned indexes.

Figure 11-8 Global Nonpartitioned Index

Text description of the illustration cncpt159.gif

Partitioned Index Examples

Example of Index Creation: Starting Table Used for Examples

CREATE TABLE employees


(employee_id NUMBER(4) NOT NULL,
last_name VARCHAR2(10),
department_id NUMBER(2))
PARTITION BY RANGE (department_id)
(PARTITION employees_part1 VALUES LESS THAN (11) TABLESPACE part1,
PARTITION employees_part2 VALUES LESS THAN (21) TABLESPACE part2,
PARTITION employees_part3 VALUES LESS THAN (31) TABLESPACE part3);

Example of a Local Index Creation

CREATE INDEX employees_local_idx ON employees (employee_id) LOCAL;

Example of a Global Index Creation

CREATE INDEX employees_global_idx ON employees(employee_id);

Example of a Global Partitioned Index Creation

CREATE INDEX employees_global_part_idx ON employees(employee_id)


GLOBAL PARTITION BY RANGE(employee_id)
(PARTITION p1 VALUES LESS THAN(5000),
PARTITION p2 VALUES LESS THAN(MAXVALUE));

Example of a Partitioned Index-Organized Table Creation


CREATE TABLE sales_range
(
salesman_id NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount NUMBER(10),
sales_date DATE,
PRIMARY KEY(sales_date, salesman_id))
ORGANIZATION INDEX INCLUDING salesman_id
OVERFLOW TABLESPACE tabsp_overflow
PARTITION BY RANGE(sales_date)
(PARTITION sales_jan2000 VALUES LESS
THAN(TO_DATE('02/01/2000','DD/MM/YYYY'))
OVERFLOW TABLESPACE p1_overflow,
PARTITION sales_feb2000 VALUES LESS
THAN(TO_DATE('03/01/2000','DD/MM/YYYY'))
OVERFLOW TABLESPACE p2_overflow,
PARTITION sales_mar2000 VALUES LESS
THAN(TO_DATE('04/01/2000','DD/MM/YYYY'))
OVERFLOW TABLESPACE p3_overflow,
PARTITION sales_apr2000 VALUES LESS
THAN(TO_DATE('05/01/2000','DD/MM/YYYY'))
OVERFLOW TABLESPACE p4_overflow);

Miscellaneous Information about Creating Indexes on Partitioned Tables

You can create bitmap indexes on partitioned tables, with the restriction that the bitmap
indexes must be local to the partitioned table. They cannot be global indexes.

Global indexes can be unique. Local indexes can only be unique if the partitioning key is
a part of the index key.

Using Partitioned Indexes in OLTP Applications

Here are a few guidelines for OLTP applications:

• Global indexes and unique, local indexes provide better performance than
nonunique local indexes because they minimize the number of index partition probes.
• Local indexes offer better availability when there are partition or subpartition
maintenance operations on the table.

Using Partitioned Indexes in Data Warehousing and DSS Applications

Here are a few guidelines for data warehousing and DSS applications:

• Local indexes are preferable because they are easier to manage during data
loads and during partition-maintenance operations.
• Local indexes can improve performance because many index partitions can
be scanned in parallel by range queries on the index key.

Partitioned Indexes on Composite Partitions


Here are a few points to remember when using partitioned indexes on composite
partitions:

• Only range partitioned global indexes are supported.


• Subpartitioned indexes are always local and stored with the table subpartition
by default.
• Tablespaces can be specified at either index or index subpartition levels.

Partitioning to Improve Performance

Partitioning can help you improve performance and manageability. Some topics to keep
in mind when using partitioning for these reasons are:

• Partition Pruning
• Partition-wise Joins
• Parallel DML

Partition Pruning

The Oracle server explicitly recognizes partitions and subpartitions. It then optimizes
SQL statements to mark the partitions or subpartitions that need to be accessed and
eliminates (prunes) unnecessary partitions or subpartitions from access by those SQL
statements. In other words, partition pruning is the skipping of unnecessary index and
data partitions or subpartitions in a query.

For each SQL statement, depending on the selection criteria specified, unneeded
partitions or subpartitions can be eliminated. For example, if a query only involves
March sales data, then there is no need to retrieve data for the remaining eleven
months. Such intelligent pruning can dramatically reduce the data volume, resulting in
substantial improvements in query performance.

If the optimizer determines that the selection criteria used for pruning are satisfied by all
the rows in the accessed partition or subpartition, it removes those criteria from the
predicate list (WHERE clause) during evaluation in order to improve performance.
However, the optimizer cannot prune partitions if the SQL statement applies a function
to the partitioning column (with the exception of the TO_DATE function). Similarly, the
optimizer cannot use an index if the SQL statement applies a function to the indexed
column, unless it is a function-based index.

Pruning can eliminate index partitions even when the underlying table's partitions
cannot be eliminated, but only when the index and table are partitioned on different
columns. You can often improve the performance of operations on large tables by
creating partitioned indexes that reduce the amount of data that your SQL statements
need to access or modify.

Equality, range, LIKE, and IN-list predicates are considered for partition pruning with
range or list partitioning, and equality and IN-list predicates are considered for partition
pruning with hash partitioning.

Partition Pruning Example


We have a partitioned table called orders. The partition key for orders is order_date.
Let's assume that orders has six months of data, January to June, with a partition for
each month of data. If the following query is run:

SELECT SUM(value)
FROM orders
WHERE order_date BETWEEN '28-MAR-98' AND '23-APR-98'

Partition pruning is achieved by:

• First, partition elimination of January, February, May, and June data


partitions. Then either:

 An index scan of the March and April data partition due to high index
selectivity

or

 A full scan of the March and April data partition due to low index
selectivity

Partition-wise Joins

A partition-wise join is a join optimization that you can use when joining two tables that
are both partitioned along the join column(s). With partition-wise joins, the join operation
is broken into smaller joins that are performed sequentially or in parallel. Another way of
looking at partition-wise joins is that they minimize the amount of data exchanged
among parallel slaves during the execution of parallel joins by taking into account data
distribution.

See Also:

Oracle9i Data Warehousing Guide for more information about


partitioning methods and partition-wise joins

Parallel DML

Parallel execution dramatically reduces response time for data-intensive operations on


large databases typically associated with decision support systems and data
warehouses. In addition to conventional tables, you can use parallel query and parallel
DML with range- and hash-partitioned tables. By doing so, you can enhance scalability
and performance for batch operations.

Managing Indexes

This chapter discusses the management of indexes, and contains the following topics:

• About Indexes
• Guidelines for Managing Indexes
• Creating Indexes
• Altering Indexes
• Monitoring Space Use of Indexes
• Dropping Indexes
• Viewing Index Information

About Indexes

Indexes are optional structures associated with tables and clusters that allow SQL
statements to execute more quickly against a table. Just as the index in this manual
helps you locate information faster than if there were no index, an Oracle Database
index provides a faster access path to table data. You can use indexes without rewriting
any queries. Your results are the same, but you see them more quickly.

Oracle Database provides several indexing schemes that provide complementary


performance functionality. These are:

• B-tree indexes: the default and the most common


• B-tree cluster indexes: defined specifically for cluster
• Hash cluster indexes: defined specifically for a hash cluster
• Global and local indexes: relate to partitioned tables and indexes
• Reverse key indexes: most useful for Oracle Real Application Clusters
applications
• Bitmap indexes: compact; work best for columns with a small set of values
• Function-based indexes: contain the precomputed value of a
function/expression
• Domain indexes: specific to an application or cartridge.

Indexes are logically and physically independent of the data in the associated table.
Being independent structures, they require storage space. You can create or drop an
index without affecting the base tables, database applications, or other indexes. The
database automatically maintains indexes when you insert, update, and delete rows of
the associated table. If you drop an index, all applications continue to work. However,
access to previously indexed data might be slower.

See Also:

Chapter 13, " Managing Space for Schema Objects" is recommended


reading before attempting tasks described in this chapter.

Guidelines for Managing Indexes

This section discusses guidelines for managing indexes and contains the following
topics:

• Create Indexes After Inserting Table Data


• Index the Correct Tables and Columns
• Order Index Columns for Performance
• Limit the Number of Indexes for Each Table
• Drop Indexes That Are No Longer Required
• Specify Index Block Space Use
• Estimate Index Size and Set Storage Parameters
• Specify the Tablespace for Each Index
• Consider Parallelizing Index Creation
• Consider Creating Indexes with NOLOGGING
• Consider Costs and Benefits of Coalescing or Rebuilding Indexes
• Consider Cost Before Disabling or Dropping Constraints

See Also:

Oracle Database Concepts for conceptual information


about indexes and indexing, including descriptions of the various
indexing schemes offered by Oracle
Oracle Database Performance Tuning Guide and
Oracle Data Warehousing Guide for information about bitmap indexes

Oracle Data Cartridge Developer's Guide for


information about defining domain-specific operators and indexing
schemes and integrating them into the Oracle Database server

Create Indexes After Inserting Table Data

Data is often inserted or loaded into a table using either the SQL*Loader or an import
utility. It is more efficient to create an index for a table after inserting or loading the data.
If you create one or more indexes before loading data, the database then must update
every index as each row is inserted.

Creating an index on a table that already has data requires sort space. Some sort space
comes from memory allocated for the index creator. The amount for each user is
determined by the initialization parameter SORT_AREA_SIZE. The database also
swaps sort information to and from temporary segments that are only allocated during
the index creation in the users temporary tablespace.

Under certain conditions, data can be loaded into a table with SQL*Loader direct-path
load and an index can be created as data is loaded.

See Also:

Oracle Database Utilities for information about using SQL*Loader for


direct-path load

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 15% of the rows in
a large table. The percentage varies greatly according to the relative speed of a table
scan and how the distribution of the row data in relation to the index key. The faster the
table scan, the lower the percentage; the more clustered the row data, the higher the
percentage.
• To improve performance on joins of multiple tables, index columns used for
joins.

Note:

Primary and unique keys automatically have indexes, but you might
want to create an index on a foreign key.

• 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 candidates for indexing:

• Values are relatively unique in the column.


• There is a wide range of values (good for regular indexes).
• There is a small range of values (good for bitmap indexes).
• The column contains many nulls, but queries often select all rows having a
value. In this case, use the following phrase:
• WHERE COL_X > -9.99 * power(10,125)

Using the preceding phrase 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 not null
values.

LONG and LONG RAW columns cannot be indexed.

The size of a single index entry cannot exceed roughly one-half (minus some overhead)
of the available space in the data block.

Order Index Columns for Performance


The order of columns in the CREATE INDEX statement can affect query performance.
In general, specify the most frequently used columns first.

If you create a single index across columns to speed up queries that access, for
example, col1, col2, and col3; then queries that access just col1, or that access just col1
and col2, are also speeded up. But a query that accessed just col2, just col3, or just
col2 and col3 does not use the index.

Limit the Number of Indexes for Each Table

A table can have any number of indexes. However, the more indexes there are, the
more overhead is incurred as the table is modified. Specifically, when rows are inserted
or deleted, all indexes on the table must be updated as well. Also, when a column is
updated, all indexes that contain the column must be updated.

Thus, there is a trade-off between the speed of retrieving data from a table and the
speed of updating the table. For example, if a table is primarily read-only, having more
indexes can be useful; but if a table is heavily updated, having fewer indexes could be
preferable.

Drop Indexes That Are No Longer Required

Consider dropping an index if:

• It does not speed up queries. The table could be very small, or there could 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.

See Also:

"Monitoring Index Usage"

Specify Index Block Space Use

When an index is created for a table, data blocks of the index are filled with the existing
values in the table up to PCTFREE. The space reserved by PCTFREE for an index
block is only used when a new row is inserted into the table and the corresponding
index entry must be placed in the correct index block (that is, between preceding and
following index entries).

If no more space is available in the appropriate index block, the indexed value is placed
where it belongs (based on the lexical set ordering). Therefore, if you plan on inserting
many rows into an indexed table, PCTFREE should be high to accommodate the new
index values. If the table is relatively static without many inserts, PCTFREE for an
associated index can be low so that fewer blocks are required to hold the index data.
PCTUSED cannot be specified for indexes.

See Also:

"Managing Space in Data Blocks" for information about the PCTFREE


parameter

Estimate Index Size and Set Storage Parameters

Estimating the size of an index before creating one can facilitate better disk space
planning and management. You can use the combined estimated size of indexes, along
with estimates for tables, the undo tablespace, and redo log files, to determine the
amount of disk space that is required to hold an intended database. From these
estimates, you can make correct hardware purchases and other decisions.

Use the estimated size of an individual index to better manage the disk space that the
index uses. When an index is created, you can set appropriate storage parameters and
improve I/O performance of applications that use the index. For example, assume that
you estimate the maximum size of an index before creating it. If you then set the
storage parameters when you create the index, fewer extents are allocated for the table
data segment, and all of the index data is stored in a relatively contiguous section of
disk space. This decreases the time necessary for disk I/O operations involving this
index.

The maximum size of a single index entry is approximately one-half the data block size.

See Also:

"Managing Storage Parameters" for specific information about storage


parameters

Specify the Tablespace for Each Index

Indexes can be created in any tablespace. An index can be created in the same or
different tablespace as the table it indexes. If you use the same tablespace for a table
and its index, it can be more convenient to perform database maintenance (such as
tablespace or file backup) or to ensure application availability. All the related data is
always online together.

Using different tablespaces (on different disks) for a table and its index produces better
performance than storing the table and index in the same tablespace. Disk contention is
reduced. But, if you use different tablespaces for a table and its index and one
tablespace is offline (containing either data or index), then the statements referencing
that table are not guaranteed to work.

Consider Parallelizing Index Creation


You can parallelize index creation, much the same as you can parallelize table creation.
Because multiple processes work together to create the index, the database can create
the index more quickly than if a single server process created the index sequentially.

When creating an index in parallel, storage parameters are used separately by each
query server process. Therefore, an index created with an INITIAL value of 5M and a
parallel degree of 12 consumes at least 60M of storage during index creation.

See Also:

Oracle Database Concepts for more information about parallel


execution

Oracle Data Warehousing Guide for information about utilizing


parallel execution in a data warehousing environment

Consider Creating Indexes with NOLOGGING

You can create an index and generate minimal redo log records by specifying
NOLOGGING in the CREATE INDEX statement.

Note:

Because indexes created using NOLOGGING are not archived, perform


a backup after you create the index.

Creating an index with NOLOGGING has the following benefits:

• Space is saved in the redo log files.


• The time it takes to create the index is decreased.
• Performance improves for parallel creation of large indexes.

In general, the relative performance improvement is greater for larger indexes created
without LOGGING than for smaller ones. Creating small indexes without LOGGING has
little effect on the time it takes to create an index. However, for larger indexes the
performance improvement can be significant, especially when you are also parallelizing
the index creation.

Consider Costs and Benefits of Coalescing or Rebuilding Indexes

Improper sizing or increased growth can produce index fragmentation. To eliminate or


reduce fragmentation, you can rebuild or coalesce the index. But before you perform
either task weigh the costs and benefits of each option and choose the one that works
best for your situation. Table 15-1 is a comparison of the costs and benefits associated
with rebuilding and coalescing indexes.

Table 15-1 To Rebuild or Coalesce ... That Is the Question


Rebuild Index Coalesce Index
Quickly moves index to another tablespace Cannot move index to another
tablespace
Higher costs: requires more disk space Lower costs: does not require
more disk space
Creates new tree, shrinks height if applicable Coalesces leaf blocks within
same branch of tree
Enables you to quickly change storage and tablespace Quickly frees up index leaf
parameters without having to drop the original index. blocks for use.

In situations where you have B-tree index leaf blocks that can be freed up for reuse, you
can merge those leaf blocks using the following statement:

ALTER INDEX vmoore COALESCE;

Figure 15-1 illustrates the effect of an ALTER INDEX COALESCE on the index vmoore.
Before performing the operation, the first two leaf blocks are 50% full. This means you
have an opportunity to reduce fragmentation and completely fill the first block, while
freeing up the second. In this example, assume that PCTFREE=0.

Figure 15-1 Coalescing Indexes

Description of the illustration admin026.gif

Consider Cost Before Disabling or Dropping Constraints

Because unique and primary keys have associated indexes, you should factor in the
cost of dropping and creating indexes when considering whether to disable or drop a
UNIQUE or PRIMARY KEY constraint. If the associated index for a UNIQUE key or
PRIMARY KEY constraint is extremely large, you can save time by leaving the
constraint enabled rather than dropping and re-creating the large index. You also have
the option of explicitly specifying that you want to keep or drop the index when dropping
or disabling a UNIQUE or PRIMARY KEY constraint.
See Also:

"Managing Integrity Constraints"

Creating Indexes

This section describes how to create indexes. To create an index in your own schema,
at least one of the following conditions must be true:

• The table or cluster to be indexed is in your own schema.


• You have INDEX privilege on the table to be indexed.
• You have CREATE ANY INDEX system privilege.

To create an index in another schema, all of the following conditions must be true:

• You have CREATE ANY INDEX system privilege.


• The owner of the other schema has a quota for the tablespaces to contain the
index or index partitions, or UNLIMITED TABLESPACE system privilege.

This section contains the following topics:

• Creating an Index Explicitly


• Creating a Unique Index Explicitly
• Creating an Index Associated with a Constraint
• Collecting Incidental Statistics when Creating an Index
• Creating a Large Index
• Creating an Index Online
• Creating a Function-Based Index
• Creating a Key-Compressed Index

Creating an Index Explicitly

You can create indexes explicitly (outside of integrity constraints) using the SQL
statement CREATE INDEX. The following statement creates an index named
emp_ename for the ename column of the emp table:

CREATE INDEX emp_ename ON emp(ename)


TABLESPACE users
STORAGE (INITIAL 20K
NEXT 20k
PCTINCREASE 75)
PCTFREE 0;

Notice that several storage settings and a tablespace are explicitly specified for the
index. If you do not specify storage options (such as INITIAL and NEXT) for an index,
the default storage options of the default or specified tablespace are automatically used.

See Also:
Oracle Database SQL Reference for syntax and restrictions on the use
of the CREATE INDEX statement

Creating a Unique Index Explicitly

Indexes can be unique or nonunique. Unique indexes guarantee that no two rows of a
table have duplicate values in the key column (or columns). Nonunique indexes do not
impose this restriction on the column values.

Use the CREATE UNIQUE INDEX statement to create a unique index. The following
example creates a unique index:

CREATE UNIQUE INDEX dept_unique_index ON dept (dname)


TABLESPACE indx;

Alternatively, you can define UNIQUE integrity constraints on the desired columns. The
database enforces UNIQUE integrity constraints by automatically defining a unique
index on the unique key. This is discussed in the following section. However, it is
advisable that any index that exists for query performance, including unique indexes, be
created explicitly.

See Also:

Oracle Database Performance Tuning Guide for more information about


creating an index for performance

Creating an Index Associated with a Constraint

Oracle Database enforces a UNIQUE key or PRIMARY KEY integrity constraint on a


table by creating a unique index on the unique key or primary key. This index is
automatically created by the database when the constraint is enabled. No action is
required by you when you issue the CREATE TABLE or ALTER TABLE statement to
create the index, but you can optionally specify a USING INDEX clause to exercise
control over its creation. This includes both when a constraint is defined and enabled,
and when a defined but disabled constraint is enabled.

To enable a UNIQUE or PRIMARY KEY constraint, thus creating an associated index,


the owner of the table must have a quota for the tablespace intended to contain the
index, or the UNLIMITED TABLESPACE system privilege. The index associated with a
constraint always takes the name of the constraint, unless you optionally specify
otherwise.

Note:
An efficient procedure for enabling a constraint that can make use of
parallelism is described in"Efficient Use of Integrity Constraints: A
Procedure".

Specifying Storage Options for an Index Associated with a Constraint

You can set the storage options for the indexes associated with UNIQUE and PRIMARY
KEY constraints using the USING INDEX clause. The following CREATE TABLE
statement enables a PRIMARY KEY constraint and specifies the storage options of the
associated index:

CREATE TABLE emp (


empno NUMBER(5) PRIMARY KEY, age INTEGER)
ENABLE PRIMARY KEY USING INDEX
TABLESPACE users
PCTFREE 0;

Specifying the Index Associated with a Constraint

If you require more explicit control over the indexes associated with UNIQUE and
PRIMARY KEY constraints, the database lets you:

• Specify an existing index that the database is to use to enforce the constraint
• Specify a CREATE INDEX statement that the database is to use to create the
index and enforce the constraint

These options are specified using the USING INDEX clause. The following statements
present some examples.

Example 1:

CREATE TABLE a (
a1 INT PRIMARY KEY USING INDEX (create index ai on a (a1)));

Example 2:

CREATE TABLE b(
b1 INT,
b2 INT,
CONSTRAINT bu1 UNIQUE (b1, b2)
USING INDEX (create unique index bi on b(b1, b2)),
CONSTRAINT bu2 UNIQUE (b2, b1) USING INDEX bi);

Example 3:

CREATE TABLE c(c1 INT, c2 INT);


CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;

If a single statement creates an index with one constraint and also uses that index for
another constraint, the system will attempt to rearrange the clauses to create the index
before reusing it.

See Also:

"Managing Integrity Constraints"

Collecting Incidental Statistics when Creating an Index

Oracle Database provides you with the opportunity to collect statistics at very little
resource cost during the creation or rebuilding of an index. These statistics are stored in
the data dictionary for ongoing use by the optimizer in choosing a plan for the execution
of SQL statements. The following statement computes index, table, and column
statistics while building index emp_ename on column ename of table emp:

CREATE INDEX emp_ename ON emp(ename)


COMPUTE STATISTICS;

See Also:

Oracle Database Performance Tuning Guide for information


about collecting statistics and their use by the optimizer

"Analyzing Tables, Indexes, and Clusters"

Creating a Large Index

When creating an extremely large index, consider allocating a larger temporary


tablespace for the index creation using the following procedure:

1. Create a new temporary tablespace using the CREATE TABLESPACE or


CREATE TEMPORARY TABLESPACE statement.
2. Use the TEMPORARY TABLESPACE option of the ALTER USER statement
to make this your new temporary tablespace.
3. Create the index using the CREATE INDEX statement.
4. Drop this tablespace using the DROP TABLESPACE statement. Then use
the ALTER USER statement to reset your temporary tablespace to your original
temporary tablespace.

Using this procedure can avoid the problem of expanding your usual, and usually
shared, temporary tablespace to an unreasonably large size that might affect future
performance.
Creating an Index Online

You can create and rebuild indexes online. This enables you to update base tables at
the same time you are building or rebuilding indexes on that table. You can perform
DML operations while the index build is taking place, but DDL operations are not
allowed. Parallel execution is not supported when creating or rebuilding an index online.

The following statements illustrate online index build operations:

CREATE INDEX emp_name ON emp (mgr, emp1, emp2, emp3) ONLINE;

Note:

While you can perform DML operations during an online index build,
Oracle recommends that you do not perform major/large DML
operations during this procedure. This is because while the DML on the
base table is taking place it holds a lock on that resource. The DDL to
build the index cannot proceed until the transaction acting on the base
table commits or rolls back, thus releasing the lock.

For example, if you want to load rows that total up to 30% of the size of
an existing table, you should perform this load before the online index
build.

See Also:

"Rebuilding an Existing Index"

Creating a Function-Based Index

Function-based indexes facilitate queries that qualify a value returned by a function or


expression. The value of the function or expression is precomputed and stored in the
index.

To create a function-based index, you must have the COMPATIBLE parameter set to
8.1.0.0.0 or higher. In addition to the prerequisites for creating a conventional index, if
the index is based on user-defined functions, then those functions must be marked
DETERMINISTIC. Also, you just have the EXECUTE object privilege on any user-
defined function(s) used in the function-based index if those functions are owned by
another user.

Additionally, to use a function-based index:

• The table must be analyzed after the index is created.


• The query must be guaranteed not to need any NULL values from the
indexed expression, since NULL values are not stored in indexes.
Note:

CREATE INDEX stores the timestamp of the most recent function used
in the function-based index. This timestamp is updated when the index
is validated. When performing tablespace point-in-time recovery of a
function-based index, if the timestamp on the most recent function used
in the index is newer than the timestamp stored in the index, then the
index is marked invalid. You must use the ANALYZE INDEX ...
VALIDATE STRUCTURE statement to validate this index.

To illustrate a function-based index, consider the following statement that defines a


function-based index (area_index) defined on the function area(geo):

CREATE INDEX area_index ON rivers (area(geo));

In the following SQL statement, when area(geo) is referenced in the WHERE clause,
the optimizer considers using the index area_index.

SELECT id, geo, area(geo), desc


FROM rivers
WHERE Area(geo) >5000;

Table owners should have EXECUTE privileges on the functions used in function-based
indexes.

Because a function-based index depends upon any function it is using, it can be


invalidated when a function changes. If the function is valid, you can use an ALTER
INDEX ... ENABLE statement to enable a function-based index that has been disabled.
The ALTER INDEX ... DISABLE statement lets you disable the use of a function-based
index. Consider doing this if you are working on the body of the function.

See Also:

Oracle Database Concepts for more information about


function-based indexes

Oracle Database Application Developer's Guide -


Fundamentals for information about using function-based indexes in
applications and examples of their use

Creating a Key-Compressed Index

Creating an index using key compression enables you to eliminate repeated


occurrences of key column prefix values.
Key compression breaks an index key into a prefix and a suffix entry. Compression is
achieved by sharing the prefix entries among all the suffix entries in an index block. This
sharing can lead to huge savings in space, allowing you to store more keys for each
index block while improving performance.

Key compression can be useful in the following situations:

• You have a nonunique index where ROWID is appended to make the key
unique. If you use key compression here, the duplicate key is stored as a prefix entry on
the index block without the ROWID. The remaining rows become suffix entries
consisting of only the ROWID.
• You have a unique multicolumn index.

You enable key compression using the COMPRESS clause. The prefix length (as the
number of key columns) can also be specified to identify how the key columns are
broken into a prefix and suffix entry. For example, the following statement compresses
duplicate occurrences of a key in the index leaf block:

CREATE INDEX emp_ename ON emp(ename)


TABLESPACE users
COMPRESS 1;

The COMPRESS clause can also be specified during rebuild. For example, during
rebuild you can disable compression as follows:

ALTER INDEX emp_ename REBUILD NOCOMPRESS;

See Also:

Oracle Database Concepts for a more detailed discussion of key


compression

Altering Indexes

To alter an index, your schema must contain the index or you must have the ALTER
ANY INDEX system privilege. Among the actions allowed by the ALTER INDEX
statement are:

• Rebuild or coalesce an existing index


• Deallocate unused space or allocate a new extent
• Specify parallel execution (or not) and alter the degree of parallelism
• Alter storage parameters or physical attributes
• Specify LOGGING or NOLOGGING
• Enable or disable key compression
• Mark the index unusable
• Start or stop the monitoring of index usage

You cannot alter index column structure.


More detailed discussions of some of these operations are contained in the following
sections:

• Altering Storage Characteristics of an Index


• Rebuilding an Existing Index
• Monitoring Index Usage

Altering Storage Characteristics of an Index

Alter the storage parameters of any index, including those created by the database to
enforce primary and unique key integrity constraints, using the ALTER INDEX
statement. For example, the following statement alters the emp_ename index:

ALTER INDEX emp_ename


STORAGE (PCTINCREASE 50);

The storage parameters INITIAL and MINEXTENTS cannot be altered. All new settings
for the other storage parameters affect only extents subsequently allocated for the
index.

For indexes that implement integrity constraints, you can adjust storage parameters by
issuing an ALTER TABLE statement that includes the USING INDEX subclause of the
ENABLE clause. For example, the following statement changes the storage options of
the index created on table emp to enforce the primary key constraint:

ALTER TABLE emp


ENABLE PRIMARY KEY USING INDEX
PCTFREE 5;

See Also:

Oracle Database SQL Reference for syntax and restrictions on the use
of the ALTER INDEX statement

Rebuilding an Existing Index

Before rebuilding an existing index, compare the costs and benefits associated with
rebuilding to those associated with coalescing indexes as described in Table 15-1.

When you rebuild an index, you use an existing index as the data source. Creating an
index in this manner enables you to change storage characteristics or move to a new
tablespace. Rebuilding an index based on an existing data source removes intra-block
fragmentation. Compared to dropping the index and using the CREATE INDEX
statement, re-creating an existing index offers better performance.

The following statement rebuilds the existing index emp_name:

ALTER INDEX emp_name REBUILD;


The REBUILD clause must immediately follow the index name, and precede any other
options. It cannot be used in conjunction with the DEALLOCATE UNUSED clause.

You have the option of rebuilding the index online. The following statement rebuilds the
emp_name index online:

ALTER INDEX emp_name REBUILD ONLINE;

If you do not have the space required to rebuild an index, you can choose instead to
coalesce the index. Coalescing an index is an online operation.

See Also:

"Creating an Index Online"

"Monitoring Space Use of Indexes"

Monitoring Index Usage

Oracle Database provides a means of monitoring indexes to determine whether they


are being used. If an index is not being used, then it can be dropped, eliminating
unnecessary statement overhead.

To start monitoring the usage of an index, issue this statement:

ALTER INDEX index MONITORING USAGE;

Later, issue the following statement to stop the monitoring:

ALTER INDEX index NOMONITORING USAGE;

The view V$OBJECT_USAGE can be queried for the index being monitored to see if
the index has been used. The view contains a USED column whose value is YES or
NO, depending upon if the index has been used within the time period being monitored.
The view also contains the start and stop times of the monitoring period, and a
MONITORING column (YES/NO) to indicate if usage monitoring is currently active.

Each time that you specify MONITORING USAGE, the V$OBJECT_USAGE view is
reset for the specified index. The previous usage information is cleared or reset, and a
new start time is recorded. When you specify NOMONITORING USAGE, no further
monitoring is performed, and the end time is recorded for the monitoring period. Until
the next ALTER INDEX ... MONITORING USAGE statement is issued, the view
information is left unchanged.

Monitoring Space Use of Indexes


If key values in an index are inserted, updated, and deleted frequently, the index can
lose its acquired space efficiently over time. Monitor index efficiency of space usage at
regular intervals by first analyzing the index structure, using the ANALYZE INDEX ...
VALIDATE STRUCTURE statement, and then querying the INDEX_STATS view:

SELECT PCT_USED FROM INDEX_STATS WHERE NAME = 'index';

The percentage of index space usage varies according to how often index keys are
inserted, updated, or deleted. Develop a history of average efficiency of space usage for
an index by performing the following sequence of operations several times:

• Analyzing statistics
• Validating the index
• Checking PCT_USED
• Dropping and rebuilding (or coalescing) the index

When you find that index space usage drops below its average, you can condense the
index space by dropping the index and rebuilding it, or coalescing it.

See Also:

"Analyzing Tables, Indexes, and Clusters"

Dropping Indexes

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

Some reasons for dropping an index include:

• The index is no longer required.


• The index is not providing anticipated performance improvements for queries
issued against the associated table. For example, the table might be very small, or there
might be many rows in the table but very few index entries.
• Applications do not use the index to query the data.
• The index has become invalid and must be dropped before being rebuilt.
• The index has become too fragmented and must be dropped before being
rebuilt.

When you drop an index, all extents of the index segment are returned to the containing
tablespace and become available for other objects in the tablespace.

How you drop an index depends on whether you created the index explicitly with a
CREATE INDEX statement, or implicitly by defining a key constraint on a table. If you
created the index explicitly with the CREATE INDEX statement, then you can drop the
index with the DROP INDEX statement. The following statement drops the emp_ename
index:
DROP INDEX emp_ename;

You cannot drop only the index associated with an enabled UNIQUE key or PRIMARY
KEY constraint. To drop a constraints associated index, you must disable or drop the
constraint itself.

Note:

If a table is dropped, all associated indexes are dropped automatically.

See Also:

Oracle Database SQL Reference for syntax and restrictions


on the use of the DROP INDEX statement

"Managing Integrity Constraints"

Viewing Index Information

The following views display information about indexes:

View Description
DBA_INDEXES DBA view describes indexes on all tables in the database. ALL
view describes indexes on all tables accessible to the user.
ALL_INDEXES USER view is restricted to indexes owned by the user. Some
columns in these views contain statistics that are generated by
USER_INDEXES the DBMS_STATS package or ANALYZE statement.
DBA_IND_COLUMNS These views describe the columns of indexes on tables. Some
columns in these views contain statistics that are generated by
ALL_IND_COLUMNS the DBMS_STATS package or ANALYZE statement.

USER_IND_COLUMNS
DBA_IND_EXPRESSIONS
These views describe the expressions of function-based indexes
on tables.
ALL_IND_EXPRESSIONS

USER_IND_EXPRESSIONS
INDEX_STATS Stores information from the last ANALYZE INDEX ... VALIDATE
STRUCTURE statement.
INDEX_HISTOGRAM Stores information from the last ANALYZE INDEX ... VALIDATE
STRUCTURE statement.
V$OBJECT_USAGE Contains index usage information produced by the ALTER
INDEX ... MONITORING USAGE functionality.

Potrebbero piacerti anche