A Brief Review of Interval Partitioning
With the introduction of interval partitioning in Oracle Database 11g, the need to manually add partitions when inserting data outside the defined range was eliminated. This article briefly reviews several important aspects of interval partitioning.
Point 1: Requirement for an Initial Range Partition
To use range-interval partitioning, at least one range partition must be defined:
SQL> create table tbl (
id number,
name varchar2(10),
date_ DATE
)
PARTITION BY RANGE (date_)
INTERVAL(NUMTOYMINTERVAL(1, ‘YEAR’))
(
PARTITION p1 VALUES LESS THAN (TO_DATE(‘4-6-2001’, ‘DD-MM-YYYY’))
);After new partitions are added automatically, you might decide to drop partition p1 (which is the only range partition):
SQL> insert into tbl values(1,’test’,TO_DATE(‘4-6-2002‘, ‘DD-MM-YYYY’));
1 row inserted
SQL> insert into tbl values(1,’test’,TO_DATE(‘4-6-2003‘, ‘DD-MM-YYYY’));
1 row inserted
SQL> select PARTITION_NAME,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME INTERVAL
—————- ——–
P1 NO
SYS_P701 YES
SYS_P702 YES
SQL> alter table TBL drop partition p1;
ORA-14758: Last partition in the range section cannot be droppedIn Oracle 11g, the first range partition cannot be dropped unless another range partition exists. To drop it, all interval partitions must first be converted to non-interval partitions:
SQL> alter table tbl set interval( numtoyminterval(1,’YEAR’));
Table altered
SQL> select PARTITION_NAME,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME INTERVAL
—————- ——–
P1 NO
SYS_P701 NO
SYS_P702 NONow the p1 partition can be dropped:
SQL> alter table TBL drop partition p1;
Table alteredIn Oracle 12c Release 2 and later, this behavior changed. The first range partition can be dropped directly, and Oracle automatically manages the transition:
SQL> select PARTITION_NAME,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME INTERVAL
——————– ——–
P1 NO
SYS_P17415 YES
SYS_P17416 YES
SQL> alter table TBL drop partition p1;
Table altered
SQL> select PARTITION_NAME,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME INTERVAL
——————– ——–
SYS_P17415 NO
SYS_P17416 YESPoint 2: Behavior of Automatically Created Interval Partitions
Consider a table partitioned using a range-interval strategy:
SQL> create table tbl (
id number,
name varchar2(10),
date_ DATE
)
PARTITION BY RANGE (date_)
INTERVAL(NUMTOYMINTERVAL(1, ‘YEAR‘))
(
PARTITION p1 VALUES LESS THAN (TO_DATE(‘4-6-2001’, ‘DD-MM-YYYY’)),
PARTITION p2 VALUES LESS THAN (TO_DATE(‘5-5-2003’, ‘DD-MM-YYYY’)),
PARTITION p3 VALUES LESS THAN (TO_DATE(‘6-4-2005’, ‘DD-MM-YYYY’))
);
Table created.When inserting rows with dates beyond the last defined range (greater than 06–04–2005), Oracle creates new interval partitions. The day and month of the new partition boundary match those of the last range partition:
SQL> insert into tbl values(7,’test’,TO_DATE(‘9-8-2041’, ‘DD-MM-YYYY’));
1 row inserted
SQL> insert into tbl values(7,’test’,TO_DATE(’10-11-2091′, ‘DD-MM-YYYY’));
1 row inserted
SQL> select PARTITION_NAME,HIGH_VALUE from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE
——————– ———–
P1 2001-06-04
P2 2003-05-05
P3 2005-04-06
SYS_P501 2042-04-06
SYS_P521 2092-04-06As shown, each newly created partition uses the same month and day (04–06) as the last range partition.
To change this behavior for future interval partitions:
- Disable interval partitioning:
SQL> alter table tbl set interval();
Table altered2. Add a new range partition with the desired date:
SQL> alter table tbl add partition p100 values less than (TO_DATE(‘3030-01-01‘,’YYYY-MM-DD’));
Table altered3.Re-enable interval partitioning:
SQL> alter table tbl set interval(NUMTOYMINTERVAL(1,’YEAR‘));
Table alteredNow, new interval partitions will be created using the new boundary:
SQL> insert into tbl values(855,’test’,TO_DATE(’12-12-4040′, ‘DD-MM-YYYY’));
1 row inserted
SQL> select PARTITION_NAME,HIGH_VALUE from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE
——————– ———–
P1 2001-06-04
P2 2003-05-05
P3 2005-04-06
SYS_P501 2042-04-06
SYS_P521 2092-04-06
P100 3030-01-01
SYS_P541 4041-01-01
7 rows selectedPoint 3: Naming Partitions
When adding a range partition, you can explicitly assign a name:
SQL> alter table tbl add partition p2040 values less than (TO_DATE(‘4-6-2040’, ‘DD-MM-YYYY’));
Table alteredIf you do not specify a name, Oracle assigns one automatically:
SQL> alter table tbl add partition values less than (TO_DATE(‘4-6-2040’, ‘DD-MM-YYYY’));
Table altered
SQL> select PARTITION_NAME,HIGH_VALUE from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE
——————– ——————–
P1 2001-06-04
SYS_P581 2040-06-04However, when interval partitioning is enabled, you cannot manually add partitions using this method:
SQL> alter table tbl add partition p4020 values less than (4);
ORA-14760: ADD PARTITION is not permitted on Interval partitioned objectsStarting with Oracle 12c Release 2, you can rename automatically created interval partitions:
SQL> select PARTITION_NAME,HIGH_VALUE,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE INTERVAL
——————– ———- ——–
P1 1 NO
SYS_P601 3 YES
SQL> alter table tbl rename partition for (2) to p3;
Table altered
SQL> select PARTITION_NAME,HIGH_VALUE,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE INTERVAL
——————– ———- ——–
P1 1 NO
P3 3 YESPoint 4: Manually Adding Partitions to a Range-Interval Table
You cannot manually add partitions to a range-interval partitioned table using the standard method (without performing DML). However, this can be achieved using one of the following approaches.
Method 1: Using LOCK TABLE ... PARTITION FOR
SQL> select PARTITION_NAME,HIGH_VALUE,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE INTERVAL
————— ———– ——–
P1 2001-06-04 NO
SQL> LOCK TABLE tbl PARTITION FOR(TO_DATE(’11-12-2021′, ‘DD-MM-YYYY’)) IN SHARE MODE;
Table(s) locked
SQL> commit;
Commit complete
SQL> select PARTITION_NAME,HIGH_VALUE,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE INTERVAL
————— ———– ——–
P1 2001-06-04 NO
SYS_P664 2022-06-04 YESA common use case for this method is performing a partition exchange:
SQL> create table tbl_non_partition as select * from tbl where 1=2;
Table created
SQL> insert into tbl_non_partition values(855,’test’,TO_DATE(’09-09-2021′, ‘DD-MM-YYYY’));
1 row inserted
SQL> insert into tbl_non_partition values(855,’test’,TO_DATE(’07-07-2021′, ‘DD-MM-YYYY’));
1 row inserted
SQL> insert into tbl_non_partition values(855,’test’,TO_DATE(’08-08-2021′, ‘DD-MM-YYYY’));
1 row inserted
SQL> insert into tbl_non_partition values(855,’test’,TO_DATE(’10-10-2021′, ‘DD-MM-YYYY’));
1 row inserted
SQL> commit;
Commit complete
SQL> ALTER TABLE tbl
EXCHANGE PARTITION FOR (TO_DATE(’11-12-2021′, ‘DD-MM-YYYY’))
WITH TABLE tbl_non_partition;
Table altered
SQL> select count(*) from tbl_non_partition;
COUNT(*)
———-
0
SQL> select count(*) from tbl PARTITION FOR (TO_DATE(’11-12-2021′, ‘DD-MM-YYYY’));
COUNT(*)
———-
4Method 2: temporary disabling interval partitioning and adding manually partitions:
SQL> ALTER TABLE tbl SET INTERVAL ();
Table altered
SQL> alter table tbl add partition p4020 values less than (TO_DATE(’11-12-2021′, ‘DD-MM-YYYY’)) ;
Table altered
SQL> select PARTITION_NAME,HIGH_VALUE,INTERVAL from user_tab_partitions where table_name=’TBL’;
PARTITION_NAME HIGH_VALUE INTERVAL
————— ———- ——–
P1 2001-06-04 NO
P4020 2021-12-11 NOPoint 5: Converting Range Partitioning to Interval Partitioning
Consider the following range-partitioned table:
create table tbl1 (
id number,
name varchar2(10),
date_ DATE
)
PARTITION BY RANGE (date_)
(
PARTITION p1 VALUES LESS THAN (TO_DATE(‘4-1-2001’, ‘DD-MM-YYYY’))
); Attempting to insert data for the year 2030 results in an error:
SQL> insert into tbl1 values(6,’test’,TO_DATE(‘4-1-2030’, ‘DD-MM-YYYY’));
ORA-14400: inserted partition key does not map to any partitionBy converting the table to interval partitioning, Oracle automatically creates new partitions for out-of-range values:
SQL> ALTER TABLE tbl1 SET INTERVAL(NUMTOYMINTERVAL(2,’YEAR’));
Table altered.
SQL> select partition_name, interval from user_tab_partitions where table_name = ‘TBL1’;
PARTITION_ INT
———- —
P1 NO
SQL> insert into tbl1 values(6,’test’,TO_DATE(‘4-1-2030’, ‘DD-MM-YYYY’));
1 row created.
SQL> select partition_name, interval from user_tab_partitions where table_name = ‘TBL1’;
PARTITION_ INT
———- —
P1 NO
SYS_P421 YESPoint 6: Converting Interval Partitioning to Range Partitioning
As shown, converting from range to interval automatically creates partition SYS_P421. To revert the table from interval to range partitioning:
SQL> ALTER TABLE tbl1 SET INTERVAL ();
Table altered.
SQL> select partition_name, interval from user_tab_partitions where table_name = ‘TBL1’;
PARTITION_ INT
———- —
P1 NO
SYS_P421 NO
SQL> insert into tbl1 values(7,’test’,TO_DATE(‘4-1-2040’, ‘DD-MM-YYYY’));
ORA-14400: inserted partition key does not map to any partitionPoint 7: Distributing Interval Partitions Across Tablespaces
When using interval partitioning, partitions can be distributed across multiple tablespaces in a round-robin fashion using the STORE IN clause:
SQL> alter table tbl1 set STORE IN(tbs1,tbs2,tbs3,tbs4);
Table altered.
Comments
Post a Comment