Oracle8i Concepts
Release 8.1.5

A67781-01

Library

Product

Contents

Index

Prev Next

11
Partitioned Tables and Indexes

Like to a double cherry, seeming parted,

But yet an union in partition;

Two lovely berries molded on one stem.

Wm. Shakespeare: A Midsummer-Night's Dream

This chapter describes partitioned tables and indexes, and explains some administrative considerations for partitioning. It covers the following topics:

Introduction to Partitioning

This section explains how partitioning can help you manage large tables and indexes in an Oracle database. It includes the following sections:

What Is Partitioning?

Partitioning addresses the key problem of supporting very large tables and indexes by allowing you to decompose them into smaller and more manageable pieces called partitions. Once partitions are defined, SQL statements can access and manipulate the partitions rather than entire tables or indexes. Partitions are especially useful in data warehouse applications, which commonly store and analyze large amounts of historical data.

Partitioning Methods

Two primary methods of partitioning are available: range partitioning, which partitions the data in a table or index according to a range of values, and hash partitioning, which partitions the data according to a hash function. Another method, composite partitioning, partitions the data by range and further subdivides the data into subpartitions using a hash function. See "Basic Partitioning Model" for more information about these partitioning methods.

Logical and Physical Attributes

All partitions of a table or index have the same logical attributes, although their physical attributes may be different. For example, all partitions in a table share the same column and constraint definitions, and all partitions in an index share the same index columns, but storage specifications and other physical attributes such as PCTFREE, PCTUSED, INITRANS, and MAXTRANS may vary for different partitions of the same table or index.

Like partitions, all subpartitions of a table or index have the same logical attributes. Unlike partitions, however, the subpartitions of a single partition cannot have different physical attributes.

Storage of Partitions and Subpartitions

A separate segment stores each partition of a range-partitioned or hash-partitioned table or index, and each subpartition of a composite-partitioned table or index. The partitions of a composite-partitioned table or index are logical structures only--they do not occupy separate segments because their data is stored in the segments of their subpartitions.

Optionally, you can store each partition (or subpartition of a composite-partitioned table or index) in a separate tablespace, which has the following advantages:

Example of a Partitioned Table

In Figure 11-1, the SALES table contains historical data divided by week number into 13 four-week partitions.

Figure 11-1 SALES Table Partitioned by Week


This SQL statement creates the range-partitioned table shown in Figure 11-1:

CREATE TABLE sales ( acct_no                  NUMBER(5), 
                                          acct_name              CHAR(30), 
                                          amount_of_sale    NUMBER(6), 
                                          week_no                  INTEGER ) 
              PARTITION BY RANGE ( week_no ) ... 
                      (PARTITION sales1 VALUES LESS THAN ( 4 ) TABLESPACE ts0, 
                        PARTITION sales2 VALUES LESS THAN ( 8 ) TABLESPACE ts1, 
                        ... 
                        PARTITION sales13 VALUES LESS THAN ( 52 ) TABLESPACE ts12 );

Additional Information:

For more examples of partitioned tables, see the Oracle8i Administrator's Guide.  

Partition Pruning

The Oracle server incorporates the intelligence to explicitly recognize partitions and subpartitions. This knowledge is exploited in optimizing SQL statements to mark the partitions or subpartitions that need to be accessed, eliminating ("pruning") unnecessary partitions or subpartitions from access by those SQL statements.

For each SQL statement, depending on the selection criteria specified, unneeded partitions or subpartitions can be eliminated. For example, if a query only involves Q1 sales data, there is no need to retrieve data for the remaining three quarters. 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.) See "DATE Datatypes".

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

The ability to prune unneeded partitions or subpartitions from SQL statements increases performance and availability for many purposes, including partition-level or subpartition-level load, purge, backup, restore, reorganization, and index building.

Partition-Wise Joins

An additional area of optimization for partitioned tables is a partition-wise join, which is a large join operation that is broken into smaller joins that are performed sequentially or in parallel.

In order to use partition-wise joining, both tables must be equipartitioned (see "Equipartitioning").

If the optimizer determines that partition-wise joining provides a performance gain, then it will be used. In some situations, the optimizer can combine pruning and partition-wise joining.

Additional Information:

For detailed information about partition-wise joins, see Oracle8i Tuning.  

Advantages of Partitioning

This section identifies the classes of databases that could benefit from the use of partitioning, and characterizes them in terms of the problems they present:

Very Large Databases (VLDBs)

A Very Large Database (VLDB) contains hundreds of gigabytes or even a few terabytes of data. Partitioning provides support for VLDBs that contain mostly structured data, rather than unstructured data. These VLDBs typically owe their size to the presence of a few very large data objects (tables and indexes) rather than to the presence of a very large number of data objects.

There are two major categories of VLDB:

A VLDB can be characterized as an OLTP database if most of its workload is OLTP. Similarly, a VLDB can be characterized as a DSS database if most of its workload consists of DSS queries.

Partitioning efficiently supports both OLTP VLDBs and DSS VLDBs.

Historical Databases

Historical databases are the most common type of DSS VLDB. They contain two classes of tables: historical tables and enterprise tables.

Partitioning addresses the problem of supporting large historical tables and their indexes by dividing historical data into time-related partitions that can be managed independently and added or deleted conveniently.

Mission-Critical Databases

Mission-critical OLTP databases present special availability and performance problems even if they are not very large. For example, it may be necessary to perform scheduled maintenance operations or recover a 10-gigabyte table in a very short period of time, perhaps an hour or less. Also, the DBA may need a degree of control over data placement that is hard to achieve when a table or index is spread over multiple drives.

Partitioning can increase 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. You can also improve access performance to a critical table or index by controlling performance parameters on a partition basis.

Reducing Downtime for Scheduled Maintenance

Partitions enable data management operations like data loads, index creation, and data purges at the partition level, rather than on the entire table, resulting in significantly reduced times for these operations.

Partitioning can significantly reduce the impact of scheduled downtime for maintenance operations:

Partition Maintenance Operations

Partition maintenance operations are faster than full table or index maintenance operations. A speedup can be achieved equal to the ratio:

(# records in full table or index) / (# records in partition)

provided there are no interpartition stored constructs (global indexes and referential integrity constraints).

To further reduce downtime, a partition maintenance operation can take advantage of performance features that are available for table and index-level maintenance operations, such as the PARALLEL, NOLOGGING, and DIRECT (or APPEND) options where applicable.

Partition Independence

Partition independence for the partition maintenance operations makes it possible to perform concurrent maintenance operations on different partitions of the same table or index, as well as concurrent SELECT and DML operations against partitions that are unaffected by maintenance operations.

For example, you can Direct Path Load into partitions PA and PB at the same time, while applications are executing standard SQL SELECT and DML operations against other partitions.

Partition independence is particularly important for operations that involve data movement. Such operations can take a long time (minutes, hours, or even days). Partitioning can reduce the window of unavailability on other partitions to a short time (few seconds) during operations that involve data movement, provided there are no inter-partition stored constructs (global indexes and referential integrity constraints).

Partition independence is not needed for short operations (no data movement) because these operations complete in a short time.

Reducing Downtime Due to Data Failures

Some maintenance operations are unplanned events, required to recover from hardware or software failures that cause data loss or corruption. Recovery from hardware failures and many system software failures is accomplished by running the RECOVER command on a database, tablespace, or datafile. Any tables or indexes that have records in a tablespace or datafile being recovered remain unavailable during recovery. Increased availability is particularly important for mission-critical OLTP databases.

Because partitions are independent of each other, the unavailability of a piece (or a subset of pieces) does not affect access to the rest of the data.

Storing partitions in separate tablespaces provides the following benefits:

DSS Performance

DSS queries on very large tables present special performance problems. An ad-hoc query that requires a table scan can take a long time, because it must inspect every row in the table; there is no way to identify and skip subsets of irrelevant rows. The problem is particularly important for historical tables, for which many queries concentrate access on rows that were generated recently.

Partitions help solve this DSS performance problem. An ad-hoc query which only requires rows that correspond to a single partition (or range of partitions) can be executed using a partition scan rather than a table scan.

For example, a query that requests data generated in the month of October 1997 can scan just the rows stored in the October 1997 partition, rather than rows generated over many years of activity. This improves response time and it can also substantially reduce the temporary disk space requirement for queries that require sorts.

I/O Performance

Partitioning can control how data is spread across physical devices. To balance I/O utilization, you can specify where to store the partitions of a table or index.

With this level of location control, you can accommodate the special needs of applications that require fast response time by reducing disk contention and using faster devices. On the other hand, data that is accessed infrequently, such as old historical data, can be moved to slow disks or stored in subsystems that support a storage hierarchy.

Disk Striping: Performance versus Availability

Disk striping and partitioning are both tools that can improve performance through the reduction of contention for disk arms. Which tool to use, or in which proportions to use them together, is an important issue to consider when physically designing databases. These issues should be considered not only with respect to performance, but also with respect to availability and partition independence.

Figure 11-2 shows the two extremes of combining partitioning and striping. Both (a) and (b) in Figure 11-2 show four partitions spread across eight disks, but (a) stripes each partition onto its own pair of disks, whereas (b) stripes each partition onto all eight disks.

Intermediate configurations are also possible, where subsets of partitions are striped over subsets of disks.

Figure 11-2 Partitions and Disk Striping


The trade-off between performance and availability must be decided when determining how to partition tables and indexes, and how to stripe the disks on which they are stored.

For mission-critical databases it is recommended that partition independence and availability be favored, therefore each partition that you want to stripe across disks should be striped onto its own set of disk drives, which should include enough drives to achieve the required I/O parallelism for accesses to that partition.

Partition Transparency

The vast majority of application programs require partition transparency, that is the programs should be insensitive to whether the data they access is partitioned and how it is partitioned.

A few application programs, however, can take advantage of partitions by explicitly requesting access to an individual partition, rather than the entire table. For example, a user might want to break a long batch job on a very large table into a sequence of short nightly batch jobs on individual partitions.

Manual Partitioning with Partition Views

Instead of using partitioned tables, you can build separate tables with identical templates and define a view that does a UNION of these tables. This is known as manual partitioning, and the view is known as a partition view. Partition views were the only form of partitioning available in Oracle7 Release 7.3. They are not recommended for new applications in Oracle8i.


Note:

Oracle8i supports partition views solely for backwards compatibility with Oracle7 Release 7.3. Future releases of Oracle will not support partition views, starting with Oracle Release 9.  


Partition views that were created for Oracle7 databases can be converted to partitioned tables by using the EXCHANGE PARTITION option of the ALTER TABLE command.

Additional Information:

See the Oracle8i Administrator's Guide for instructions on converting partition views to partitioned tables.  

The basic idea behind partition views is to divide a large table into multiple physical tables using a WHERE clause or CHECK constraint as a partitioning criterion, then glue the smaller tables together into a whole with a UNION ALL view. You can then define sets of "base indexes" with identical key specifications on the base tables, which provide indexing capabilities when the UNION ALL view is used. (Partition views must be indexed to work properly.) Compared to nonpartitioned tables, partition views should not add significant CPU overhead. Queries that use a key range to select from a partition view access only the base tables that lie within the key range. The optimizer can use separate execution plans for a partition view's base tables. (In contrast, the optimizer uses a single execution plan for all partitions in a partitioned table.)

Disadvantages of Partition Views

Manual partitioning with partition views has many disadvantages in comparison with partitioned tables:

Guidelines for Partition Views

To create and maintain partition views, follow the guidelines in Table 11-1.


Table 11-1 Partition View Guidelines

To use partition views, the PARTITION_VIEW_ENABLED parameter must be set.  

DDL commands must be issued separately for each underlying table. For example, to add an index to a partition view, you must add indexes to all underlying tables. To analyze a partition view, you must analyze all underlying tables. However, you can submit operations on each partition in parallel.  

Administrative operations must be performed as operations on the underlying tables of the partition view, not on the partition view itself. For example, a split operation consists of either one or two CREATE TABLE AS SELECT operations (one if the split is "in place"), followed by a redefining of the partition view's view text.  

You can create referential integrity constraints on underlying tables, but for the constraints to be true for the partition view, the primary key must contain the partition column.  

Similarly, you can have an unique index on underlying tables, but for uniqueness to be true for the partition view, the partition column must be contained in the unique index. (You can have only one unique index.)  

Every partition has its own index, so any index lookup must be done in all indexes for partitions that are not skipped.  

A partition view cannot be the target of a DML statement (UPDATE, INSERT, or DELETE).  

Partition views do not support concatenated partitioning keys.  

SQL*Loader does not support partition views.  

Basic Partitioning Model

This section describes the basic partitioning model, which includes these partitioning methods:

and these additional topics:

You can partition a table or index with options to the CREATE TABLE or CREATE INDEX statement. After creating a partitioned table or index, you can use an ALTER TABLE or ALTER INDEX statement to modify its partitioning attributes.

The partitioning syntax for CREATE TABLE and CREATE INDEX statements is very similar. The CREATE TABLE statement specifies:

  1. The logical attributes of the table, such as column and constraint definitions.

  2. The physical attributes of the table.

    • If the table is nonpartitioned, these are the real physical attributes of the segment associated with the table.

    • If the table is partitioned, these table-level attributes specify defaults for the individual partitions of the table.

  3. For a partitioned table, there is also a partition specification that includes:

    • the table-level algorithm used to map rows to partitions

    • a list of partition descriptions, one for each partition in the table

    • a list of subpartition descriptions (only for composite partitioning).

    Each partition description includes a clause defining supplemental partition-level information about the algorithm used to map rows to partitions. This clause can also specify a partition name and physical attributes for the partition.

    Each subpartition description (for composite partitioning) can specify a subpartition name and a tablespace for the subpartition.

Datatype Restrictions

Partitioned tables cannot have any columns with LONG or LONG RAW datatypes. If a table or index is partitioned on a column that has the DATE datatype and if the NLS date format does not specify the century with the year, the partition descriptions must use the TO_DATE function to specify the year completely; otherwise you cannot create the table or index.

See "DATE Datatypes" for examples.

Bitmap Restrictions

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. (See "Index Partitioning".)

Cost Based Optimization

Cost based optimization is used when a SQL statement accesses partitioned tables or indexes; rule base optimization is not available for partitions. A single execution plan is used for all partitions of a partitioned table.

Statistics can be gathered by partition or subpartition, using the DBMS_STATS package or the ANALYZE command. It is important to gather statistics whenever the nature of the data in a partitioned table changes significantly. The statistics can be found in these data dictionary views:


ALL_TAB_PARTITIONS, DBA_TAB_PARTITIONS, USER_TAB_PARTITIONS  

ALL_TAB_SUBPARTITIONS, DBA_TAB_SUBPARTITIONS, USER_TAB_SUBPARTITIONS  

ALL_IND_PARTITIONS, DBA_IND_PARTITIONS, USER_IND_PARTITIONS  

ALL_IND_SUBPARTITIONS, DBA_IND_SUBPARTITIONS, USER_IND_SUBPARTITIONS  

ALL_PART_COL_STATISTICS, DBA_PART_COL_STATISTICS, USER_PART_COL_STATISTICS  

ALL_SUBPART_COL_STATISTICS, DBA_SUBPART_COL_STATISTICS, USER_SUBPART_COL_STATISTICS  

Range Partitioning

Range partitioning maps rows to partitions based on ranges of column values. Range partitioning is defined by the partitioning specification for a table or index:

PARTITION BY RANGE ( column_list ) 

and by the partitioning specifications for each individual partition:

VALUES LESS THAN ( value_list ) 

where:

In each partition, all rows (or rows pointed to by index entries) have partitioning keys that compare less than the partition bound for that partition. Unless the partition is the first partition in the table or index, all of its partitioning keys also compare greater than or equal to the partition bound for the previous partition. See "Partition Bounds for Range Partitioning" for more information about how partitioning keys are compared to partition bounds, including how multicolumn partitioning keys are handled.

For example, in the following table of four partitions (one for each quarter's sales), a row with SALE_YEAR=1997, SALE_MONTH=7, and SALE_DAY=18 has partitioning key (1997, 7, 18); therefore it belongs in the third partition and would be stored in tablespace TSC. A row with SALE_YEAR=1997, SALE_MONTH=7, and SALE_DAY=1 has partitioning key (1997, 7, 1) and also belongs in the third partition, stored in tablespace TSC.

CREATE TABLE sales
    ( invoice_no NUMBER, 
      sale_year  INT NOT NULL,
      sale_month INT NOT NULL,
      sale_day   INT NOT NULL )
  PARTITION BY RANGE (sale_year, sale_month, sale_day)
    ( PARTITION sales_q1 VALUES LESS THAN (1997, 04, 01) 
        TABLESPACE tsa,
      PARTITION sales_q2 VALUES LESS THAN (1997, 07, 01) 
        TABLESPACE tsb,
      PARTITION sales_q3 VALUES LESS THAN (1997, 10, 01) 
        TABLESPACE tsc,
      PARTITION sales_q4 VALUES LESS THAN (1998, 01, 01) 
        TABLESPACE tsd ); 

You can use the ALTER TABLE MERGE PARTITIONS command to merge the contents of two adjacent range partitions into one partition. You might want to do this to keep historical data online in larger partitions. For example, you might want to have daily partitions, with the oldest partition rolled up into weekly partitions, which can then be rolled up into monthly partitions, and so on.

Hash Partitioning

Although partitioning by range is well-suited for historical databases, it may not be the best choice for other purposes. Another method of partitioning, hash partitioning, uses a hash function on the partitioning columns to stripe data into partitions. Hash partitioning allows data that does not lend itself to range partitioning to be easily partitioned for performance reasons (such as parallel DML, partition pruning, and partition-wise joins).

Hash partitioning is a better choice than range partitioning when:

The number of partitions should be a power of two (2, 4, 8, and so on) to obtain the most even data distribution. Hash partitions can be named and stored in specific tablespaces. Local indexes on hash partitions are equipartitioned with the table data. For local index partitions, you can specify the partition names and tablespaces.

The following example creates a table that names and stores a hash partition in a specific tablespace:

CREATE TABLE product( ... )
    STORAGE (INITIAL 10M)
  PARTITION BY HASH(column_list)
   ( PARTITION p1 TABLESPACE h1,
     PARTITION p2 TABLESPACE h2 );

The concepts of splitting, dropping, and merging partitions do not apply to hash partitions. However, you can increase or decrease the number of partitions by using ALTER TABLE to ADD or COALESCE hash partitions.

Composite Partitioning

Composite partitioning partitions data using the range method and, within each partition, subpartitions it using the hash method. This type of partitioning supports historical operations data at the partition level and parallelism (parallel DML) and data placement at the subpartition level.

Composite partitioning:

The partitions of a composite-partitioned table or index are logical structures only--their data is stored in the segments of their subpartitions.

The following example creates a table that uses composite partitioning (assuming the NLS DATE format is DD-MON-YYYY):

CREATE TABLE orders(
     ordid NUMBER,
     orderdate DATE,
     productid NUMBER,
     quantity NUMBER)
  PARTITION BY RANGE(orderdate)
  SUBPARTITION BY HASH(productid) SUBPARTITIONS 8
  STORE IN(ts1,ts2,ts3,ts4,ts5,ts6,ts7,ts8)
   ( PARTITION q1 VALUES LESS THAN('01-APR-1998'),
     PARTITION q2 VALUES LESS THAN('01-JUL-1998'),
     PARTITION q3 VALUES LESS THAN('01-OCT-1998'),
     PARTITION q4 VALUES LESS THAN(MAXVALUE));

In this example, the ORDERS table is range partitioned on the ORDERDATE key, in four separate ranges representing quarters of the year. Each range partition is further subpartitioned on the PRODUCTID key into eight subpartitions, for a total of 32 subpartitions. Each tablespace contains one subpartition from each partition.

The following example creates a table that uses composite partitioning with each subpartition explicitly named and stored in a specified tablespace:

CREATE TABLE orders( ... )
  PARTITION BY RANGE(orderdate)
  SUBPARTITION BY HASH(productid) SUBPARTITIONS 8
  STORE IN (ts1,ts2,ts3,ts4,ts5,ts6,ts7,ts8)
   ( PARTITION q1 VALUES LESS THAN('01-APR-1998')
     ( SUBPARTITION q1_h1 TABLESPACE ts1,
       ...
       SUBPARTITION q1_h7 TABLESPACE ts7,
       SUBPARTITION q1_h8 TABLESPACE ts8)
     PARTITION q2 VALUES LESS THAN('01-JUL-1998'), ... );

Partition and Subpartition Names

Every partition or subpartition has a name, which must conform to the usual rules for naming schema objects and their parts. In particular:

For composite partitioning, the names of subpartitions and partitions are in the same namespace; that is, a partition and a subpartition belonging to the same parent table or index cannot have the same name.

You can rename a partition or subpartition; however, you cannot create any synonyms on a partition or subpartition name.

Additional Information:

See Oracle8i SQL Reference for more information about the rules for naming schema objects.  

Referencing a Partition or Subpartition

Partition and subpartition names can optionally be referenced in DDL and DML statements and in utility statements like Import/Export and SQL*Loader. They always appear in context with the name of their parent table or index and they are never qualified by a schema name. (The schema name can be used to qualify the parent table or index.) For example:

ALTER TABLE admin.patient_visits DROP PARTITION pv_dec92; 
SELECT * FROM sales PARTITION (s_nov97) s WHERE s.amount_of_sale > 1000; 

See "Partition-Extended and Subpartition-Extended Table Names" for more information about referencing partitions and subpartitions in SQL statements.

Partitioning and Subpartitioning Columns and Keys

The partitioning columns (or subpartitioning columns) of a table or index consist of an ordered list of columns whose values determine how the data is partitioned (or subpartitioned). This list can include up to 16 columns, and cannot include any of the following types of columns:

A row's partitioning key is an ordered list of its values for the partitioning columns. Similarly, in composite partitioning a row's subpartitioning key is an ordered list of its values for the subpartitioning columns. Oracle applies either the range or hash method to each row's partitioning key (or subpartitioning key) to determine which partition (or subpartition) the row belongs in.

Partition Bounds for Range Partitioning

In a range-partitioned table or index, the partitioning key of each row is compared with a set of upper and lower bounds to determine which partition the row belongs in. (See "Range Partitioning" for a general description of range partitioning.)

The partition bounds collectively define an ordering of the partitions in a table or index. The "first" partition is the partition with the lowest VALUES LESS THAN clause, and the "last" or "highest" partition is the partition with the highest VALUES LESS THAN clause.

Comparing Partitioning Keys with Partition Bounds

If you attempt to insert a row into a table and the row's partitioning key is greater than or equal to the partition bound for the highest partition in the table, the insert will fail.

When comparing character values in partitioning keys and partition bounds, characters are compared according to their binary values. However, if a character consists of more than one byte, Oracle compares the binary value of each byte, not of the character. The comparison also uses the comparison rules associated with the column data type (for example, blank-padded comparison is done for the ANSI CHAR data type). The NLS parameters, specifically the initialization parameters NLS_SORT and NLS_LANGUAGE and the environment variable NLS_LANG, have no effect on the comparison.

See "Multicolumn Partitioning Keys" for more information about comparing partitioning keys.

MAXVALUE

You can specify the keyword MAXVALUE for any value in the partition bound value_list. This keyword represents a virtual "infinite" value that sorts higher than any other value for the data type, including the NULL value.

For example, you might partition the OFFICE table on STATE (a CHAR(10) column) into three partitions with the following partition bounds:

Nulls

NULL cannot be specified as a value in a partition bound value_list. An empty string also cannot be specified as a value in a partition bound value_list, because it is treated as NULL within the database server.

For the purpose of assigning rows to partitions, Oracle sorts nulls greater than all other values except MAXVALUE. Nulls sort less than MAXVALUE.

This means that if a table is partitioned on a nullable column, and the column is to contain nulls, then the highest partition should have a partition bound of MAXVALUE for that column. Otherwise the rows that contain nulls will map above the highest partition in the table and the insert will fail.

DATE Datatypes

If the partition key includes a column that has the DATE datatype and the NLS date format does not specify the century with the year, you must specify partition bounds using the TO_DATE() function with a 4-character format mask for the year; otherwise you will not be able to create the table or index.

For example, you might create the SALES table using a DATE column:

CREATE TABLE sales 
    ( invoice_no NUMBER,
      sale_date DATE NOT NULL ) 
  PARTITION BY RANGE (sale_date) 
    ( PARTITION sales_q1 
        VALUES LESS THAN (TO_DATE('1997-04-01','YYYY-MM-DD')) 
        TABLESPACE tsa,
      PARTITION sales_q2 
        VALUES LESS THAN (TO_DATE('1997-07-01','YYYY-MM-DD')) 
        TABLESPACE tsb,
      PARTITION sales_q3 
        VALUES LESS THAN (TO_DATE('1997-10-01','YYYY-MM-DD')) 
        TABLESPACE tsc,
      PARTITION sales_q4 
        VALUES LESS THAN (TO_DATE('1998-01-01','YYYY-MM-DD')) 
        TABLESPACE tsd ); 

When you query or modify data, it is recommended that you use the TO_DATE() function in the WHERE clause so that the value of the date information can be determined at compile time. However, the optimizer can prune partitions using a selection criterion on partitioning columns of type DATE when you use another format, as in the following examples:

SELECT * FROM sales 
  WHERE s_saledate BETWEEN TO_DATE('01-JUL-94', 'DD-MON-YY') 
  AND TO_DATE('01-OCT-94', 'DD-MON-YY');
   
SELECT * FROM sales 
  WHERE s_saledate BETWEEN '01-JUL-1994' AND '01-OCT-1994';

In this case, the date value will be complete only at runtime. Therefore you will not be able to see which partitions Oracle is accessing as is usually shown on the partition_start and partition_stop columns of the EXPLAIN PLAN command output on the SQL statement. Instead, you will see the keyword 'KEY' for both columns.

Multicolumn Partitioning Keys

When a table or index is partitioned by range on multiple columns, each partition bound and partitioning key is a list (or vector) of values. The partition bounds and keys are ordered according to ANSI SQL2 vector comparison rules. (This is also the way Oracle orders multicolumn index keys.)

To compare a partitioning key with a partition bound, you compare the values of their corresponding columns until you find an unequal pair and then that pair determines which vector is greater. The values of any remaining columns have no effect on the comparison.

In mathematical terms, for vectors V1 and V2 which contain the same number of values, Vx[i] is the ith value in Vx. Assuming that V1[i] and V2[i] have compatible datatypes:

For example, if the partition bound for partition P is (7, 5, 10) and the partition bound for the next lower partition is (6, 7, 3) then:

If MAXVALUE appears as an element of a partition bound value_list, then the values of all the following elements are irrelevant. For example, a partition bound of (10, MAXVALUE, 5) is equivalent to a partition bound of (10, MAXVALUE, 6) or to a partition bound of (10, MAXVALUE, MAXVALUE).

Multicolumn partitioning keys are useful when the primary key for the table contains multiple columns, but rows are not distributed evenly over the most significant column in the key. For example, suppose that the SUPPLIER_PARTS table contains information about which suppliers provide which parts, and the primary key for the table is (SUPPNUM, PARTNUM). It is not sufficient to partition on SUPPNUM because some suppliers might provide hundreds of thousands of parts, while others provide only a few specialty parts. Instead, you can partition the table on (SUPPNUM, PARTNUM).

Multicolumn partitioning keys are also useful when you represent a date as three CHAR columns instead of a DATE column.

Implicit Constraints Imposed by Partition Bounds

If you specify a partition bound other than MAXVALUE for the highest partition in a table, this imposes an implicit CHECK constraint on the table. This constraint is not recorded in the data dictionary (but the partition bound itself is recorded).

Equipartitioning

Two tables or indexes are equipartitioned when:

They do not have to be the same type of schema object; for example, a table and an index can be equipartitioned.

Range Equipartitioning

If A and B are range-partitioned tables or indexes, where A[i] is the ith partition in A and B[i] is the ith partition in B, then A and B are equipartitioned if all of the following are true:

If Apcol[i] is the ith partitioning column in A and Bpcol[i] is the ith partitioning column in B, then the following must also be true:

A[i] and B[i] may differ in their physical attributes; in particular they do not have to reside in the same tablespace.

Equipartitioning is important to consider when designing the database.

Example of Equipartitioning

Figure 11-3 shows four logically related schema objects that are equipartitioned:

The logical relationship between the four schema objects is shown on the left in Figure 11-3; the physical partitioning is shown on the right. (Triangles represent indexes and rectangles represent tables.)

Figure 11-3 Equipartitioned Tables and Indexes


Rules for Partitioning Tables and Indexes

This section describes the rules for creating partitioned tables and indexes and the physical attributes of partitions.

Table Partitioning

The rules for partitioning tables are simple:

Physical Attributes of Table Partitions

This section discusses the physical attributes of table partitions for range, hash, and composite partitioning.

Range and Hash Partitioning

Default physical attributes are initially specified when the CREATE TABLE statement creates a partitioned table. Since there is no segment corresponding to the partitioned table itself, these attributes are only used in derivation of physical attributes of member partitions. Default physical attributes can later be modified using ALTER TABLE MODIFY DEFAULT ATTRIBUTES.

For hash partitioning, all partitions have the same physical characteristics and so the only physical attribute you can specify for a partition is its tablespace.

Physical attributes of table partitions created by CREATE TABLE or ALTER TABLE ADD PARTITION are determined as follows:

For hash partitioning, ALTER TABLE MOVE PARTITION can be used to move the partition to a different tablespace. For range partitioning, this statement can move the partition or modify its physical attributes. Resulting attributes are determined as follows:

For range partitioning, the physical attributes of table partitions created by ALTER TABLE SPLIT PARTITION are determined as follows:

Physical attributes of all partitions of a table may be modified by ALTER TABLE, for example, ALTER TABLE tablename NOLOGGING changes the logging mode of all partitions of tablename to NOLOGGING.

See "Tablespace and Storage Attributes of LOB Data Partitions" for additional information about the physical attributes of table partitions that contain LOB datatypes.

Composite Partitioning

For composite partitioning, the partitions specify default physical attributes for the subpartitions and the subpartitions are similar to hash partitions, in that the only physical attribute you can specify explicitly for a subpartition is its tablespace.

The default physical attributes are initially specified when the CREATE TABLE statement creates a composite partitioned table. Since there is no segment corresponding to the partitions or to the table itself, these attributes are only used in derivation of the attributes for member subpartitions. The default attributes can later be modified using ALTER TABLE MODIFY DEFAULT ATTRIBUTES or ALTER TABLE MODIFY DEFAULT ATTRIBUTES FOR PARTITION.

The physical attributes for subpartitions created by CREATE TABLE or ALTER TABLE ADD PARTITION are determined as follows:

ALTER TABLE MOVE SUBPARTITION can be used to move a subpartition to a different tablespace, but it does not change other physical attributes of the subpartition. ALTER TABLE MODIFY PARTITION modifies the physical attributes of all of that partition's existing subpartitions as well as the default physical attributes of the partition itself. You can use the FOR PARTITION clause of ALTER TABLE MODIFY PARTITION to avoid changing the attributes of existing subpartitions. Attributes modified at the table level affect the defaults at all three levels: table, partition, and subpartition.

See "Tablespace and Storage Attributes of LOB Data Partitions" for additional information about the physical attributes of table subpartitions that contain LOB datatypes.

Index Partitioning

The rules for partitioning indexes are similar to those for tables:

However, partitioned indexes are more complicated than partitioned tables because there are four types of partitioned indexes: local prefixed, local nonprefixed, global prefixed, and global nonprefixed. These types are described below. Oracle supports three of the four types (global nonprefixed indexes are not useful in real applications).

Local Partitioned Indexes

In a local index, all keys in a particular index partition refer only to rows stored in a single underlying table partition. A local index is created by specifying the LOCAL attribute.

Oracle constructs the local index so that it is equipartitioned with the underlying table. Oracle partitions the index on the same columns as the underlying table, creates the same number of partitions or subpartitions, and gives them the same partition bounds as corresponding partitions of the underlying table.

Oracle also maintains the index partitioning automatically when partitions in the underlying table are added, dropped, merged, or split, or when hash partitions or subpartitions are added or coalesced. This ensures that the index remains equipartitioned with the table.

A local index can be created UNIQUE if the partitioning columns form a subset of the index columns. This restriction guarantees that rows with identical index keys always map into the same partition, where uniqueness violations can be detected.

Local indexes have the following advantages:

Local Prefixed Indexes

A local index is prefixed if it is partitioned on a left prefix of the index columns.

For example, if the SALES table and its local index SALES_IX are partitioned on the WEEK_NUM column, then index SALES_IX is local prefixed if it is defined on the columns (WEEK_NUM,XACTION_NUM). On the other hand, if index SALES_IX is defined on column PRODUCT_NUM then it is not prefixed.

Figure 11-4 shows another example of a local prefixed index.

Local prefixed indexes can be unique or nonunique.

Figure 11-4 Local Prefixed Index


Local Nonprefixed Indexes

A local index is nonprefixed if it is not partitioned on a left prefix of the index columns.

You cannot have a unique local nonprefixed index unless the partitioning key is a subset of the index key.

Figure 11-5 shows an example of a local nonprefixed index.

Figure 11-5 Local Nonprefixed Index


Global Partitioned Indexes

In a global partitioned index, the keys in a particular index partition may refer to rows stored in more than one underlying table partition or subpartition. A global index can only be range-partitioned, but it can be defined on any type of partitioned table (range, hash, or composite partitioned).

A global index is created by specifying the GLOBAL attribute. The database administrator is responsible for defining the initial partitioning of a global index at creation and for maintaining the partitioning over time. Index partitions can be merged or split as necessary.

Normally, a global index is not equipartitioned with the underlying table. There is nothing to prevent an index from being equipartitioned with the underlying table, but Oracle does not take advantage of the equipartitioning when generating query plans or executing partition maintenance operations. So an index that is equipartitioned with the underlying table should be created as LOCAL.

A global partitioned index contains (conceptually) a single B*-tree with entries for all rows in all partitions. Each index partition may contain keys that refer to many different partitions or subpartitions in the table.

The highest partition of a global index must have a partition bound all of whose values are MAXVALUE. This insures that all rows in the underlying table can be represented in the index.

Prefixed and Nonprefixed Global Partitioned Indexes

A global partitioned index is prefixed if it is partitioned on a left prefix of the index columns. (See Figure 11-6 for an example.) A global partitioned index is nonprefixed if it is not partitioned on a left prefix of the index columns. Oracle does not support global nonprefixed partitioned indexes.

Global prefixed partitioned indexes can be unique or nonunique.

Nonpartitioned indexes are treated as global prefixed nonpartitioned indexes.

Management of Global Partitioned Indexes

Global partitioned indexes are harder to manage than local indexes:

Figure 11-6 Global Prefixed Partitioned Index


Summary of Partitioned Index Types

Table 11-2 summarizes the three types of partitioned indexes that Oracle supports.

Importance of Nonprefixed Indexes

Nonprefixed indexes are particularly useful in historical databases. In a table containing historical data, it is common for an index to be defined on one column to support the requirements of fast access by that column, but partitioned on another column (the same column as the underlying table) to support the time interval for rolling out old data and rolling in new data.

Consider the SALES table presented in Figure 11-1 ("SALES Table Partitioned by Week"). It contains a year's worth of data, divided into 13 partitions. It is range partitioned on WEEK_NO, four weeks to a partition. You might create a nonprefixed local index SALES_IX on SALES. The SALES_IX index is defined on ACCT_NO because there are queries that need fast access to the data by account number. However, it is partitioned on WEEK_NO to match the SALES table. Every four weeks the oldest partitions of SALES and SALES_IX are dropped and new ones are added.

Performance Implications of Prefixed and Nonprefixed Indexes

It is more expensive to probe into a nonprefixed index than to probe into a prefixed index.

If an index is prefixed (either local or global) and Oracle is presented with a predicate involving the index columns, then partition pruning can restrict application of the predicate to a subset of the index partitions.

For example, in Figure 11-4 ("Local Prefixed Index"), if the predicate is DEPTNO=15, the optimizer knows to apply the predicate only to the second partition of the index. (If the predicate involves a bind variable, the optimizer will not know exactly which partition but it may still know there is only one partition involved, in which case at run time, only one index partition will be accessed.)

When an index is nonprefixed, Oracle often has to apply a predicate involving the index columns to all N index partitions. This is required to look up a single key, or to do an index range scan. For a range scan, Oracle must also combine information from N index partitions. For example, in Figure 11-5 ("Local Nonprefixed Index"), a local index is partitioned on CHKDATE with an index key on ACCTNO. If the predicate is ACCTNO=31, Oracle probes all 12 index partitions.

Of course, if there is also a predicate on the partitioning columns, then multiple index probes might not be necessary. Oracle takes advantage of the fact that a local index is equipartitioned with the underlying table to prune partitions based on the partition key. For example, if the predicate in Figure 11-5 is CHKDATE<3/97, Oracle only has to probe two partitions.

So for a nonprefixed index, if the partition key is a part of the WHERE clause (but not of the index key) the optimizer determines which index partitions to probe based on the underlying table partition.

When many queries and DML statements using keys of local, nonprefixed, indexes have to probe all index partitions, this effectively reduces the degree of partition independence provided by such indexes.

Guidelines for Partitioning Indexes

When deciding how to partition indexes on a table, consider the mix of applications that need to access the table. There is a trade-off between performance on the one hand and availability and manageability on the other. Here are some of the guidelines you should consider:

Physical Attributes of Index Partitions

Default physical attributes are initially specified when a CREATE INDEX statement creates a partitioned index. Since there is no segment corresponding to the partitioned index itself, these attributes are only used in derivation of physical attributes of member partitions. Default physical attributes can later be modified using ALTER INDEX MODIFY DEFAULT ATTRIBUTES.

Physical attributes of partitions created by CREATE INDEX are determined as follows:

Physical attributes (other than TABLESPACE, as explained above) of partitions of local indexes created in the course of processing ALTER TABLE ADD PARTITION are set to the default physical attributes of each index.

Physical attributes (other than TABLESPACE, as explained above) of index partitions created by ALTER TABLE SPLIT PARTITION are determined as follows:

Physical attributes of an existing index partition can be modified by ALTER INDEX MODIFY PARTITION and ALTER INDEX REBUILD PARTITION. Resulting attributes are determined as follows:

Physical attributes of global index partitions created by ALTER INDEX SPLIT PARTITION are determined as follows:

Physical attributes of all partitions of an index (along with default values) may be modified by ALTER INDEX, for example, ALTER INDEX indexname NOLOGGING changes the logging mode of all partitions of indexname to NOLOGGING.

See "Tablespace and Storage Attributes of LOB Index Partitions" for additional information about the physical attributes of LOB index partitions.

Partitioning of Tables with LOB Columns

Tables that contain LOB columns (see "LOB Datatypes") can be partitioned; however, a partitioning key cannot contain a LOB column. The LOB data and LOB index segments of a LOB column are equipartitioned with the base table.


Note:

Although this section makes a distinction between the LOB data and LOB index, they are not separate entities. The LOB index, which is implicitly created and maintained by the system, contains control information and is an integral part of LOB column storage.  


For every partition of a partitioned table that contains a LOB column, there is a LOB data segment for the LOB data partition and a LOB index segment for the LOB index partition. These data and index segments contain the LOBs that belong to the rows in that partition.

Similarly, for every subpartition of a composite-partitioned table that contains a LOB column, there is a LOB data segment for the LOB data subpartition and a LOB index segment for the LOB index subpartition. These data and index segments contain the LOBs that belong to the rows in that subpartition. In the following discussion, "partition" refers either to a partition of a range- or hash-partitioned table or index or to a subpartition of a composite-partitioned table or index.

Equipartitioning of LOB data and LOB index segments localizes the effects of maintenance operations, resulting in more efficient use of resources and improved availability of data. See "Partition Maintenance Operations on Tables with LOB Columns".

Tablespace and Storage Attributes of LOB Data Partitions

The algorithm for determining a tablespace for a given LOB data partition is similar to that for determining a tablespace for a LOCAL index partition. In determining values of physical storage attributes other than TABLESPACE for LOB data partitions, Oracle uses the same algorithm that determines the values of physical attributes for table partitions. Note that you can explicitly specify the LOB storage characteristics for a specific LOB column at the partition level or at the table level.

TABLESPACE Attribute of LOB Data Partitions

The following rules determine the tablespace of a LOB data partition:

  1. If a tablespace is specified for a given LOB data partition, that value is used.

  2. Otherwise, if a default TABLESPACE value, other than "TABLESPACE DEFAULT", is specified at the table level for all LOB data partitions of a given LOB column of the table, that value is used.

  3. Otherwise, the LOB data partition is co-located with the table partition to which it corresponds.

The following example illustrates these rules:

CREATE TABLE PT1 (A NUMBER, B BLOB, C CLOB, D CLOB)
   LOB (B,D) STORE AS (STORAGE (NEXT 15K))
   LOB (C) STORE AS (TABLESPACE TSB)
   PARTITION BY RANGE (A)
   (PARTITION P VALUES LESS THAN (MAXVALUE) TABLESPACE TS1
      LOB (B) STORE AS (TABLESPACE TSA),                      (Rule 1)
      LOB (C) STORE AS (PCTVERSION 20),                       (Rule 2)
      LOB (D) STORE AS (STORAGE (NEXT 10K)))                  (Rule 3)
   TABLESPACE TSX; 

In this example, the tablespace for the LOB data partitions corresponding to partition P are determined as follows:

See "Tablespace and Storage Attributes of LOB Index Partitions" for a discussion of how to determine a tablespace in which a LOB index partition is located.

Other Storage Attributes of LOB Data Partitions

The values of the storage attributes (other than TABLESPACE) for a LOB data partition are determined as follows:

  1. If a value is specified for a given LOB data partition, that value is used.

  2. Otherwise, if a default value is specified at the table level for all LOB data partitions of a given LOB column of the table, that value is used.

  3. Otherwise, the system or tablespace default value is used. However, in the case of LOGGING, if CACHE is explicitly specified then LOGGING is used regardless of the tablespace value (because CACHE NOLOGGING is not supported).

See the next section for a discussion of how the storage attributes for a LOB index partitions are determined.

Tablespace and Storage Attributes of LOB Index Partitions

LOB index partitions always reside in the same tablespace as the LOB data partitions to which they correspond, that is, the LOB index partitions are co-located with the LOB data partitions. All other attributes of a LOB index partition are determined based on attributes of the LOB data partition to which they correspond and default attributes of the tablespace in which both the LOB data and its corresponding LOB index partition reside.


Note:

You cannot specify any attributes for a LOB index or any of its partitions.  


TABLESPACE Attribute of LOB Index Partitions

The following example shows how LOB index partitions collocate with the LOB data partitions to which they correspond:

CREATE TABLE PT1 (A NUMBER, B BLOB, C CLOB, D CLOB)
   LOB (B,D) STORE AS (STORAGE (NEXT 15K))
   LOB (C) STORE AS (TABLESPACE TSB);
   PARTITION BY RANGE (A) 
   (PARTITION P VALUES LESS THAN (MAXVALUE) TABLESPACE TS1
      LOB (B) STORE AS (TABLESPACE TSA),                      (Rule 1)
      LOB (C) STORE AS (PCTVERSION 20),                       (Rule 2)
      LOB (D) STORE AS (STORAGE (NEXT 10K)))                  (Rule 3)
   TABLESPACE TSX; 

In this example, the LOB index partitions that correspond to LOB data partitions associated with partition P are located in the following tablespaces:

Other Storage Attributes of LOB Index Partitions

The values of the storage attributes (other than TABLESPACE) for a LOB index partition are determined based on the values of attributes of a corresponding LOB data partition and the default attributes of the tablespace in which the LOB index partition is located.

Views and Partitioned LOBs

Regular views on partitioned tables with LOB columns work the same way that they do on tables without LOB columns. Object views can also be created on top of partitioned tables with LOB columns.

The same view-based privilege checking is performed on LOBs selected from views on partitioned tables as for LOBs selected from views on nonpartitioned tables. The user must have privileges to access the LOB through the view from which the LOB locator is obtained (SELECTed). This view-based privilege checking is necessary for snapshots (that is, materialized views used for replication).

BFILEs in Partitioned Tables

For BFILEs, only the LOB locator is stored in the table while the actual BFILE data exists in an external operating system file. Therefore the BFILE locator is what gets partitioned with the rest of the table, not the BFILE data. The BFILE locator is of varying length and stores the directory alias and file name along with other control information. Thus, a BFILE column in a partitioned table is similar to a VARCHAR2 column in a partitioned table.

Partitioning Index-Organized Tables and Their Secondary Indexes

You can partition an index-organized table by range of column values. An index-organized table differs from a regular (heap-organized) table in the following ways:

See "Index-Organized Tables" for more information.

When partitioning an index-organized table, note the following:

Range Partitioning and Primary Key Columns

Restricting the partitioning columns to a subset of the primary key columns ensures that when you insert a row into a partition, the uniqueness of the primary key can be verified by searching that partition. (Without this restriction, it would be necessary to search other partitions as well, and so the partitions would not be independent of each other.)

When the partitioning columns form a prefix of the primary key columns, the partition bounds form a sequence in primary key order. For queries that require data from more than one partition, a simple concatenation of resulting rows from each partition preserves the primary key order. This is the optimal way of partitioning an index-organized table.

When the partitioning columns do not form a prefix of the primary key columns, each partition's data is sorted in primary key order but selecting rows from more than one partition in primary key order requires a merge of the individually sorted partition rows.

If you want to partition an index-organized table on columns that are not a subset of the primary key columns, you can use this workaround:

  1. Make the partitioning columns part of the primary key by adding them at the end.

  2. Define a unique constraint on the original primary key columns.

For example, for an index-organized table that has columns A, B, and C with a primary key (A, B), if you want to partition the table on column C you should change the primary key to (A, B, C) and define a unique constraint on (A, B). Then an insert operation will insert the row into the target partition and insert the key values for (A,B) into a nonpartitioned index on (A,B), which verifies the uniqueness across all the partitions.

Index-Organized Tables without Row Overflow

To create a partitioned index-organized table without row overflow, you need to specify ORGANIZATION INDEX at the table level only. All partitions inherit the ORGANIZATION INDEX property from the table.

You can specify default values for physical attributes at the table level and can override them at the partition level. These attributes apply to the primary key index segment that is created for each partition. The tablespace for an index segment can be specified at the partition level or at the table level; if it is not specified at either level, the user's default tablespace is used.

The following example shows the creation of an index-organized table with no row overflow:

CREATE TABLE orders(
   id NUMBER, odate DATE, ... 
   PRIMARY KEY(id, odate))
   ORGANIZATION INDEX
   PARTITION BY RANGE(odate)
 ( PARTITION p1 ... TABLESPACE q1,
   PARTITION p2 ... TABLESPACE q2);

In this example, the index organized table ORDERS is range partitioned on the ODATE column, with each partition stored in its own tablespace. No overflow is provided for.

Index-Organized Tables with Row Overflow

The overflow option allows storing the tail portion of a row in an overflow data segment. The following are the key aspects for partitioned index-organized tables with overflow:

The following example shows the creation of a partitioned index-organized table with partitioned overflow stored in a single tablespace:

CREATE TABLE orders(
    id NUMBER, odate DATE, notes VARCHAR2(1000), ...
    PRIMARY KEY(id, odate))
    ORGANIZATION INDEX INCLUDING odate
    OVERFLOW TABLESPACE all_overflow
    PARTITION BY RANGE(odate)
     ( PARTITION p1 ... TABLESPACE q1,
       PARTITION p2 ... TABLESPACE q2);

In this example, the table has a separate tablespace for overflow data segments. Even though they are stored in the same physical tablespace (ALL_OVERFLOW), the overflow data segments are partitioned on the same partition columns as used in the index-organized table. Note the use of the INCLUDING ODATE clause--this means that all data, past and including the ODATE column, will be stored in the overflow.

The following example shows the creation of a partitioned index-organized table with partitioned overflow stored in multiple tablespaces:

CREATE TABLE orders(
    id NUMBER, odate DATE, notes VARCHAR2(1000), ...
    PRIMARY KEY(id, odate))
    ORGANIZATION INDEX INCLUDING odate
    PARTITION BY RANGE(odate)
     ( PARTITION p1 ... TABLESPACE q1
       OVERFLOW TABLESPACE q1_overflow,
       PARTITION p2 ... TABLESPACE q2
       OVERFLOW TABLESPACE q2_overflow);

In this example, each partitioned overflow segment is stored in its own tablespace.

Partitioned Secondary Indexes on Index-Organized Tables

You can create local prefixed, local non-prefixed, and global prefixed partitioned indexes on index-organized tables. Indexes on index-organized tables store primary key-based (logical) rowids as opposed to physical rowids, and may contain additional "guess"data as part of the rowid to speed up secondary index-based access. See "Secondary Indexes on Index-Organized Tables" and "Logical Rowids" for more information.

For accessing an index-organized table partition by its global partition index, Oracle identifies the partition based on the logical rowid. This is possible because the rowid contains primary key columns, which in turn contain all of the partitioning columns. Once the partition is identiifed, Oracle can use the "guess" to directly access the leaf block that would hold the index row. If the "guess" is invalid, an index scan on the relevant partition B*-tree is required.

DML Partition Locks and Subpartition Locks

DML table locks synchronize DML statements (INSERT, UPDATE, and DELETE) with DDL statements and LOCK TABLE statements. DML table locks also synchronize DDL and LOCK TABLE statements among themselves. For partitioned or subpartitioned tables, Oracle uses DML partition locks or DML subpartition locks to provide partition independence for DDL and utility operations.

Partition independence (or subpartition independence) allows you to perform DDL and utility operations on selected partitions or subpartitions without reducing activity on other partitions or subpartitions.

DML Partition Locks

A partition lock protects the data in an individual partition of a partitioned table while multiple users are accessing that partition or other partitions in the table concurrently.

Partition locks fall between table locks and row locks in the DML locking hierarchy:

Partition locks can be acquired in the same modes as table locks: Share (S), Exclusive (X), Row Share (SS), Row Exclusive (SX), and Share Row Exclusive (SSX). See "Concurrency Model for Maintenance Operations" for more information about partition locking for DML and DDL statements.

Partition Locking During DML Operations on LOB Columns

When updating a LOB as a whole or only partially (using DBMS_LOB operations), in addition to acquiring a DML SX-lock on a partitioned table, Oracle acquires DML SX-lock(s) on one or more table partitions.

DML Subpartition Locks

DML subpartition locks allow you to perform DDL and utility operations on selected subpartitions without reducing activity on other subpartitions of the same partition (as well as on subpartitions of other partitions.)

A subpartition lock protects the data in an individual subpartition while multiple users are accessing that subpartition or other subpartitions in the same partition, or some subpartitions in other partitions of the table concurrently.

Oracle does not acquire DML partition locks when performing DML or DDL operations on composite partitioned tables:

As with partition locks, subpartition locks fall between table locks and row locks in the DML locking hierarchy:

Subpartition DML locks can be acquired in the same modes as table and partition DML locks: Share (S), Exclusive (X), Row Share (SS), Row Exclusive (SX), and Share Row Exclusive (SSX).

Performance Considerations for Oracle Parallel Server

Introducing an extra level of DML locking may affect the performance of short transactions in the Oracle Parallel Server environment because extra messages are sent to the Distributed Lock Manager.

To improve performance in the Oracle Parallel Server environment, you can turn off DML locking on selected tables with the ALTER TABLE DISABLE TABLE LOCK statement, which disables both table and partition DML locks. DDL statements are not allowed when DML locking is disabled.

Additional Information:

See Oracle8i Parallel Server Concepts and Administration.  

Maintenance Operations

This section covers the following topics:

For the purposes of this chapter, a maintenance operation is a DDL statement that alters a table or index definition or a utility (such as Export, Import, or SQL*Loader) that performs bulk load or unload of data.

Most maintenance operations on nonpartitioned tables and indexes also work on partitioned tables and indexes. For example, DROP TABLE can drop a partitioned table, and Export can export a partitioned table. However, some maintenance operations must be performed on individual partitions rather than the whole partitioned table or index. For example, ALTER TABLE ALLOCATE EXTENT cannot be used for a range-partitioned table; instead, you use ALTER TABLE MODIFY PARTITION ALLOCATE EXTENT for the partition or partitions that need new extents.

Maintenance operations are considered fast if their expected duration is not affected by the size (number of records) of the schema objects they operate upon. Fast maintenance operations result only in dictionary and segment header changes, and do not cause data scans and data updates. They are expected to complete in a short time (order of seconds). For example, RENAME is a fast operation while CREATE INDEX is not a fast operation.

Partition Maintenance Operations

A partition maintenance operation modifies one partition of a partitioned table or index. For example, you might add a new partition to an existing table, or you might move a partition to a different tablespace for better I/O load balancing, or you might load a partition.

Some partition maintenance operations are planned events. For example, in a historical database, the database administrator (DBA) periodically drops the oldest partitions from the database and adds a set of new partitions. This drop and add operation occurs on a regularly scheduled basis. Another example of a planned maintenance operation is a periodic Export/Import to recluster data and reduce fragmentation.

Other partition maintenance operations are unplanned events, required to recover from application or system problems. For example, unexpected transaction activity may force the DBA to split a partition to rebalance I/O load, or the DBA may need to rebuild one or more index partitions.

The partition maintenance operations are:

For information about maintenance of LOB data, see "Partition Maintenance Operations on Tables with LOB Columns".

Additional Information:

See ALTER TABLE and ALTER INDEX in the Oracle8i SQL Reference for detailed information about partition maintenance operations.  

Concurrency Model for Maintenance Operations

The concurrency model described in this section defines when it is possible to run more than one DDL and utility operation on the same schema object at the same time. It also defines which query and DML operations can be run concurrently with DDL and utility operations.

The model applies to all DDL statements. It also applies to utilities like SQL*Loader.

One-Step and Three-Step Operations

There are two types of maintenance operations, one-step and three-step.

One-step operations:

Three-step operations:

Finally, some operations may follow either one-step or three-step protocol:

Conventional Path SQL*Loader and Import use SQL INSERT so they are classified as DML operations for the purposes of the model. Export uses SQL SELECT so it is classified as a query operation.

Operations That Can Run Concurrently

The rules in this section can be derived from the definitions of one-step and three-step operations.

While a one-step operation is in progress:

Since queries (READ operations) do not take DML locks, queries are allowed on a partition which is being split or moved while the SPLIT or MOVE is being processed. However, the current segments are dropped at the end of the operation, and the space may be reused. An error is signalled if the space is reused.

While an ALTER TABLE MOVE PARTITION, ALTER TABLE SPLIT PARTITION, ALTER TABLE EXCHANGE PARTITION, or Direct Path Load Table Partition is in progress on a partition:

While a CREATE INDEX or ALTER INDEX REBUILD PARTITION or ALTER INDEX DROP/SPLIT PARTIITON applied to a USABLE partition (for a global index) is in progress:

While an ALTER INDEX REBUILD PARTITION (for a local index) is in progress on a partition which corresponds to an underlying table partition:

Some maintenance operations on a partition of a table cause the global indexes of the table or the index partitions to become UNUSABLE. An example is ALTER TABLE MOVE PARTITION. The DBA has to run a script that includes global index rebuilds in addition to the partition maintenance operation. Consequently from a user point of view these operations serialize access to the entire table. Operations such as ALTER TABLE MOVE/SPLIT PARTITION make UNUSABLE any nonpartitioned global indexes as well as all partitions of partitioned global indexes.

Note that table partition operations which mark all partitions of global indexes also mark one partition of local index (the partition corresponding to the table partition being operated on) UNUSABLE.

Similarly some partition maintenance operations require disabling Referential Integrity Constraints before the operation, and re-enabling them afterwards. An example is a ALTER TABLE DROP PARTITION of a nonempty partition. The DBA has to run a script that includes constraint re-enabling in addition to the partition maintenance operation. Consequently, from a user point of view these operations serialize access to the entire table.

Table 11-3 shows the operations that can be performed concurrently with maintenance operations on subpartitions.


Table 11-3 Concurrent Operations on Subpartitions
Maintenance Operation  Operations That Can Be Performed Concurrently 

ALTER TABLE/INDEX MODIFY DEFAULT ATTRIBUTES OF PARTITION

ALTER TABLE EXCHANGE SUBPARTITION WITHOUT VALIDATION

ALTER TABLE/INDEX MODIFY SUBPARTITION (unless ALLOCATE EXTENT is specified)

ALTER TABLE/INDEX RENAME SUBPARTITION  

Queries on the table  

ALTER TABLE MODIFY PARTITION ADD SUBPARTITION

ALTER TABLE MODIFY PARTITION COALESCE SUBPARTITION  

Queries on the table

DML as long as no attempt is made to modify contents of the subpartitions affected by the statement

Maintenance operations on other partitions and their subpartitions

Maintenance operations on other subpartitions of the partition

ALTER INDEX REBUILD SUBPARTITION on subpartitions of local indexes corresponding to other subpartitions of the same partition or to subpartitions of other partitions of the table  

ALTER TABLE EXCHANGE SUBPARTITION WITH VALIDATION

ALTER TABLE/INDEX MODIFY SUBPARTITION ALLOCATE EXTENT

ALTER TABLE MOVE SUBPARTITION

LOAD SUBPARTITION  

Queries on the table

DML as long as no attempt is made to modify contents of the subpartition(s) referenced by the statement

Maintenance operations on other partitions and their subpartitions

Maintenance operations on other subpartitions of the partition

ALTER INDEX REBUILD SUBPARTITION on subpartitions of local indexes corresponding to other subpartitions of the same partition or to subpartitions of other partitions of the table  

IMPORT SUBPARTITION  

Queries on the table

DML on the table

Maintenance operations on other partitions and their subpartitions

Maintenance operations on other subpartitions of the partition

ALTER INDEX REBUILD SUBPARTITION on subpartitions of local indexes corresponding to other subpartitions of the same partition or to subpartitions of other partitions of the table  

EXPORT PARTITION  

Any operation on the table and indexes defined on it, their partitions, and subpartitions  

ALTER (local) INDEX REBUILD SUBPARTITION  

Queries on the table

DML as long as no attempt is made to modify contents of the subpartition corresponding to the index subpartition being rebuilt

Maintenance operations on subpartitions of the index's partitions, other than the partition whose subpartition is being rebuilt

Maintenance operations on other subpartitions of the index partition

CREATE new indexes on the underlying table

Maintenance operations on existing indexes on the underlying table, as well as their partitions and subpartitions (if applicable)

Maintenance operations on partitions of the underlying table, other than the partition corresponding to the index partition whose subpartition is being rebuilt

Maintenance operations on subpartitions of the underlying table, other than the one corresponding to the index subpartition being rebuilt  

Partition Maintenance Operations on Tables with LOB Columns

Table partition maintenance operations handle partitioned tables with LOB columns (see "Partitioning of Tables with LOB Columns") as follows:

Addition of LOB columns to partitioned tables has no effect on the concurrency model for maintenance operations (see "Concurrency Model for Maintenance Operations").

Queries and Partition Maintenance Operations

Queries whose execution starts before invocation of a partition maintenance operation, or before dictionary updates are done during a partition maintenance operation, correctly access via Consistent Read the data of the affected partitions as existing at query snapshot time. Such queries either successfully complete returning all relevant data as present at snapshot time, or fail to complete returning error ORA-8103 or ORA-1410. The application should reissue the query if one of these errors is returned.

Queries that use a partitioned index, and that start with some of the index partitions marked as INDEX UNUSABLE, return an error when they actually access one of these partitions for the first time. This happens even if the partition has been made USABLE after query start.

Cursor Invalidation

Although many of the new DDL statements are partition-based, cursor invalidation is still table-based. This means that any DDL statement that modifies table T also invalidates all cursors that depend on T, even if the statement affects only one partition P of T and the cursors do not access partition P.

LOGGING and NOLOGGING Operations

All partition maintenance operations can be run in LOGGING mode. However, some operations support a NOLOGGING option:

LOGGING is the default, except when the database operates in NOARCHIVELOG mode in which case NOLOGGING is the default. DDL and utility statements that do not support the LOGGING/NOLOGGING option always run in recoverable mode (LOGGING).


Note:

LOGGING or NOLOGGING is not an attribute of an operation but of a physical object; hence, you cannot specify LOGGING or NOLOGGING in an INSERT statement. Instead, if you want to alter the logging mode of a table or index(es) involved in an insert operation, you need to issue ALTER TABLE/INDEX [NO]LOGGING before issuing the INSERT statement. For more information, see "Logging Mode".  


Managing Indexes

You can always rename, change the physical storage attributes, or rebuild a partition of a local or global index. Changing how an index is partitioned must be handled differently depending on whether the index is local or global.

Local Indexes

Oracle guarantees that the partitioning of a local index matches the partitioning of the underlying table. It does this by automatically creating or dropping index partitions as necessary when you alter the underlying table. You cannot explicitly add, drop, or split a partition in a local index.

For each local index:

When Oracle creates a new local index partition (via ADD or SPLIT of the corresponding table partition):

Rather than dropping a local index partition explicitly (for example, before loading data into its corresponding table partition), you can EXCHANGE the table partition into a nonpartitioned table, drop the index on that table and perform your load operation, then create the index and EXCHANGE the table back into the partition using the INCLUDING INDEXES option.

Global Partitioned Indexes

The DBA is responsible for maintaining the partitioning of a global index. You can drop or split a partition in a global index. However, you cannot add a partition to a global index because the high partition of a global index always has a partition bound of MAXVALUE. See "Management of Global Partitioned Indexes" for more information on managing global indexes.

Rebuild Index Partition

The ALTER INDEX REBUILD PARTITION statement can be used to regenerate a single partition in a local or global partitioned index. This saves you from having to perform DROP INDEX and then CREATE INDEX, which would affect all partitions in the index.

ALTER INDEX REBUILD PARTITION has four important applications:

INDEX UNUSABLE Attribute

Some maintenance operations mark indexes INDEX UNUSABLE (IU). INDEX UNUSABLE is an attribute of a nonpartitioned index and of a partition in a partitioned index. When an index or index partition is marked IU, you get an error if you try to execute a SELECT or DML statement that requires the index (or partition).

When a single index partition is marked IU, you must rebuild the partition to make it valid again before using it. However, while one partition is marked IU the other partitions of the index are valid and you can execute SELECT or DML statements that require the index as long as the statements do not access the IU partition.

You can also split or rename the IU partition before rebuilding it, and you can drop an IU partition of a GLOBAL index.

When a nonpartitioned index is marked IU, you can drop the index. You can also drop an IU partition of a GLOBAL index.x and re-create it, and you can use ALTER INDEX REBUILD to rebuild a nonpartitioned index.

Six types of maintenance operations can mark index partitions INDEX UNUSABLE. In all cases, you must rebuild the index partitions when the operation is complete.

Privileges for Partitioned Tables and Indexes

Privileges for partitions are granted on the parent table or index, not on individual partitions. If you want to grant access to a table on a per-partition basis, you can define a view on a partition of a table and then grant privileges on that view (see "Viewing Partitions or Subpartitions as Tables").

If a user or role has the privileges required to perform an Oracle operation on nonpartitioned tables and indexes (including the necessary resource privileges), then the same Oracle operations are allowed on partitioned tables and indexes. For example:

If a user or role has the privileges required to perform an ALTER operation on a table or index, then the ALTER operations on partitions of the table or index can be invoked, with some exceptions.

Additional Information:

See Oracle8i SQL Reference for information about privileges for the ALTER TABLE and ALTER INDEX commands.  

Auditing for Partitioned Tables and Indexes

All of the ALTER TABLE PARTITION operations are audited just like ALTER TABLE operations. No additional audit attributes are used for partitions.

Partition-Extended and Subpartition-Extended Table Names

You can perform bulk operations at the partition or subpartition level; that is, bulk operations can be restricted to just the rows of a particular partition or subpartition. For example, if you want to drop a partition without making all the global indexes UNUSABLE, you would want to delete all the rows from just that partition.

Such operations are very naturally expressed with a SQL extension that provides syntax for partition-extended table names and subpartition-extended table names. Trying to phrase the same operations with a WHERE clause predicate is often cumbersome, especially when a range partitioning key uses multiple columns.

PARTITION and SUBPARTITION Specifications

The table specification syntax for the following DML statements can contain an optional PARTITION specification for partitioned tables, or an optional PARTITION or SUBPARTITION specification for composite-partitioned tables:

For example:

SELECT * FROM schema.table PARTITION part_name; 

For a composite-partitioned table, using the PARTITION specification restricts the operation to data contained in all subpartitions of the specified partition.

Additional Information:

See Oracle8i SQL Reference for information about the syntax of DML statements.  

Viewing Partitions or Subpartitions as Tables

The PARTITION or SUBPARTITION syntax for table specifications provides a simple way of viewing individual partitions or subpartitions as tables: You can use the partition-extended table name or subpartition-extended table name to create a view that selects from just one partition or subpartition, and this view can then be used in place of a table. For example:

CREATE VIEW sales_feb98_v1 AS 
  SELECT * FROM sales SUBPARTITION (feb98_s1); 

SELECT * FROM sales_feb98_v1; 

With such views you can also build partition-level or subpartition-level access control mechanisms by granting (revoking) privileges on these views to (from) other users or roles.


Note:

For application portability and ANSI syntax compliance, you should always use views to insulate your applications from this Oracle proprietary extension.  


Using Partition- and Subpartition-Extended Table Names

This section describes restrictions on the use of the PARTITION and SUBPARTITION options in table specifications, and provides examples of SQL statements that include the PARTITION or SUBPARTITION option.

Restrictions on Partition- and Subpartition-Extended Table Names

The use of partition- and subpartition-extended table names has the following restrictions:

  1. A partition- or subpartition-extended table name cannot refer to a remote schema object.

    A partition- or subpartition-extended table name cannot contain a database link or a synonym which translates to a table with a database link. If you need to use remote partitions or subpartitions, you can create a view at the remote site which uses the partition- or subpartition-extended table name syntax and refer to that remote view.

  2. The partition- or subpartition-extended table name syntax is not supported by PL/SQL.

    A SQL statement that has the partition- or subpartition-extended table name syntax cannot be used in a PL/SQL block, although it can be used through dynamic SQL with the DBMS_SQL package. If you need to refer to a partition or subpartition within a PL/SQL block, you can use views which in turn use the partition- or subpartition-extended table name syntax.

  3. Only base tables are allowed.

    A partition or subpartition extension must be specified with a base table. No synonyms, views, or any other schema objects are allowed.

Examples of Using the PARTITION Specification

The following statements contain valid partition-extended table names:

SELECT * FROM sales PARTITION (nov97) s 
    WHERE s.amount_of_sale > 1000; 

UPDATE sales PARTITION (feb98) s 
    SET s.account_name = UPPER(s.account_name); 

DELETE FROM sales PARTITION (nov97) 
    WHERE amount_of_sale != 0; 

INSERT INTO sales PARTITION (oct97) 
    SELECT * FROM lastest_data; 

INSERT INTO sales PARTITION (oct97) 
  VALUES (...); 

INSERT INTO sales PARTITION (oct97) 
  (acct_no, ..., week_no) 
  VALUES (...); 

LOCK TABLE sales PARTITION (jun98) IN EXCLUSIVE MODE; 

CREATE VIEW sales_feb98 AS 
    SELECT * FROM sales PARTITION (feb98); 

Examples of Using the SUBPARTITION Specification

The following statements contain valid subpartition-extended table names:

SELECT * FROM sales SUBPARTITION (nov97_s1) s 
  WHERE s.amount_of_sale > 1000; 

UPDATE sales SUBPARTITION (feb98_s4) s 
  SET s.account_name = UPPER(s.account_name); 

DELETE FROM sales SUBPARTITION (nov97_s3) 
  WHERE amount_of_sale != 0; 

INSERT INTO sales SUBPARTITION (oct97_s5) 
  SELECT * FROM lastest_data; 

INSERT INTO sales SUBPARTITION (oct97_s2) 
  VALUES (...); 

INSERT INTO sales SUBPARTITION (oct97_s4) 
  (acct_no, ..., week_no) 
  VALUES (...); 

LOCK TABLE sales SUBPARTITION (jun98_s1) IN EXCLUSIVE MODE; 

CREATE VIEW sales_feb98_1 AS 
  SELECT * FROM sales SUBPARTITION (feb98_s1); 



Prev

Next
Oracle
Copyright © 1999 Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index