When dealing with a RANGE partitioned table, the defined partitions dictate all of the data that can be placed into the table. For example, if I have a SALES table as per below
SQL> create table SALES
2 ( cal_year date,
3 txn_id int,
...
...
24 )
25 partition by range ( cal_year )
26 (
27 partition p_low values less than ( date '2000-01-01' ),
28 partition p2000 values less than ( date '2001-01-01' ),
...
...
34 partition p2016 values less than ( date '2017-01-01' )
35 );
Table created.
then the existing partitions define a natural upper bound on the value of CAL_YEAR that I can insert into the table. For example, if I attempt to add a row for the year 2018, I get the familiar ORA-14400 that has called out many a DBA at the stroke of midnight on New Years Eve
SQL> insert into SALES
2 values ( date '2018-01-01', .... );
insert into SALES
*
ERROR at line 1:
ORA-14400: inserted partition key does not map to any partition
As many will know, the resolution to this is either a maintenance task to ensure that there are sufficient partitions defined, or to use the INTERVAL partitioning method, which came available in 11g.
SQL> create table SALES
2 ( cal_year date,
3 txn_id int,
...
...
23 )
24 partition by range ( cal_year )
25 INTERVAL( NUMTOYMINTERVAL(1,'YEAR'))
26 (
27 partition p_low values less than ( date '2000-01-01' ),
28 );
Table created.
And I can observe partitions being created as required as data is added to the table
SQL> select PARTITION_NAME, HIGH_VALUE
2 from user_tab_partitions
3 where table_name = 'SALES';
PARTITION_NAME HIGH_VALUE
------------------------- --------------------------------
P00 TIMESTAMP' 2000-01-01 00:00:00'
SQL> insert into SALES
2 values ( to_date('12-DEC-2011'),....);
SQL> select PARTITION_NAME, HIGH_VALUE
2 from user_tab_partitions
3 where table_name = 'SALES';
PARTITION_NAME HIGH_VALUE
------------------------- --------------------------------
P00 TIMESTAMP' 2000-01-01 00:00:00'
SYS_P362 TIMESTAMP' 2012-01-01 00:00:00'
But this isn’t a post about how interval partitioning is defined, because it’s a topic that is now well understood and well detailed in the documentation and on many blogs.
I wanted to touch on a something more subtle that you might encounter when using interval partitioned tables. Let me do a query on the SALES table, which has been recreated (as INTERVAL partitioned) but is empty. Here is the execution plan when I query the table.
SQL> select * from SALES; --empty
-------------------------------------------------------------
| Id | Operation | Name | Rows | Pstart| Pstop |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | |
| 1 | PARTITION RANGE ALL| | 1 | 1 |1048575|
| 2 | TABLE ACCESS FULL | SALES | 1 | 1 |1048575|
-------------------------------------------------------------
Wow! One million partitions ! That might seem odd, because we know that our table has been defined only with a single partition, and even that might not be instantiated yet depending on our choice of “deferred_segment_creation” parameter on the database. But the explanation is relatively simple. The moment we define a table as interval partitioned, we in effect know “in advance” the definition of every single interval that will ever follow. The starting point for the intervals is known due to the initial partition definition in the DDL, and the size/length of the interval maps out every possible future partition.
The maximum number of partitions is 1048575, which is then reflected in the execution plan.
You’ll see similar information when you create an index on such a table. If the index is local, and hence follows the same partitioning scheme as the underlying table, then it too has potentially 1048575 partitions all not yet in use, but known in advance. So if you look at the PARTITION_COUNT column for such an index, you’ll also see that the database will state that it has a (very) high partition count
SQL> create index sales_ix on sales ( some_col ) local;
Index created.
SQL> select TABLE_NAME,INDEX_NAME,PARTITION_COUNT from user_part_indexes;
TABLE_NAME INDEX_NAME PARTITION_COUNT
------------------------------ ------------------------------ ---------------
SALES SALES_IX 1048575
1 row selected.
So if you see anything suggesting one million partitions, double check to see if you really have that many.
Ooh ! Never noticed this. Although I do see that the COST in the Explain Plan may not be very high.
1m partitions is the limit for a table so it just may be saying from to ‘1 to max limit’.