Fast SPLIT PARTITION operation is unusually slow

I recently observed that the total time taken to split an empty partition, in 10.2.0.5, has increased by many fold—i.e. from under 30 seconds to 60 minutes.

SPLIT PARTITION operation is, simply, creating two new partitions and redistributing the rows from the partition being split into the two new partitions. Often one new partition contains all the rows from the partition being split, while other does not contain any rows; Oracle database engine can detect such situations and can optimize the split operation, such optimization is referred as fast SPLIT PARTITION operation.

Database Administrator’s Guide, 10g Release 2, explains how the split works and the conditions should be met to achieve fast SPLIT PARTITION operation. Oracle support document 378138.1 mentions that accurate statistics should be gathered not just on the (sub) partition to be split, but on the indexes of the table as well to achieve fast SPLIT PARTITION. The reason for this is that oracle executes recursive queries on the (sub)partition to be split in order to see the number of rows AT <value> and >= AT <value>, so that it can be determined whether one of the resulting partitions is empty.

Also, Oracle support document 1268714.1 shows how to perform a fast SPLIT PARTITION and how to verify with a simple test case.

  • First split of an empty partition took about 6 seconds.
-- Partition statistics before 1st split

SELECT dtp.table_name, dtp.partition_name, dtp.num_rows
  FROM dba_tab_partitions dtp
 WHERE	   dtp.table_name = 'RAM_SLOW_PART_TAB2'
       AND dtp.partition_name IN ('RSLP2_SEP_2017',
				  'RSLP2_OCT_2017',
				  'RSLP2_NOV_2017',
				  'RSLP2_DEC_2017',
				  'RSLP2_MAX_PART');

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS        
------------------------------ ------------------------------ ----------        
RAM_SLOW_PART_TAB2             RSLP2_SEP_2017                          0        
RAM_SLOW_PART_TAB2             RSLP2_MAX_PART                          0        

2 rows selected.

Elapsed: 00:00:00.08

-- Perform 1st Split

ALTER TABLE RAM_SLOW_PART_TAB2
   SPLIT PARTITION RSLP2_MAX_PART
      AT (TO_DATE ('2017-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
      INTO (PARTITION RSLP2_OCT_2017, PARTITION RSLP2_MAX_PART);

Table altered.

Elapsed: 00:00:05.77
  • However, a subsequent split of empty partition took about 28 minutes; as a result of database engine executing recursive queries to obtain number of rows due to missing statistics.
-- Partition statistics after 1st split

SELECT dtp.table_name, dtp.partition_name, dtp.num_rows
  FROM dba_tab_partitions dtp
 WHERE	   dtp.table_name = 'RAM_SLOW_PART_TAB2'
       AND dtp.partition_name IN ('RSLP2_SEP_2017',
				  'RSLP2_OCT_2017',
				  'RSLP2_NOV_2017',
				  'RSLP2_DEC_2017',
				  'RSLP2_MAX_PART');

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS        
------------------------------ ------------------------------ ----------        
RAM_SLOW_PART_TAB2             RSLP2_OCT_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_SEP_2017                          0        
RAM_SLOW_PART_TAB2             RSLP2_MAX_PART                                   

3 rows selected.

Elapsed: 00:00:00.08

-- Perform 2nd Split

ALTER TABLE RAM_SLOW_PART_TAB2
   SPLIT PARTITION RSLP2_MAX_PART
      AT (TO_DATE ('2017-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
      INTO (PARTITION RSLP2_NOV_2017, PARTITION RSLP2_MAX_PART);

Table altered.

Elapsed: 00:27:30.04
  • As you see, below, if you gather statistics on empty partition, time taken by the database engine to perform a fast SPLIT PARTITION operation is under 2 seconds.
-- Gather statistics for MAX partition

BEGIN
   DBMS_STATS.GATHER_TABLE_STATS (ownname	=> 'LABUSER',
				  tabname	=> 'RAM_SLOW_PART_TAB2',
				  partname	=> 'RSLP2_MAX_PART',
				  granularity	=> 'PARTITION');
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:03.99

-- Partition statistics before 3rd split

SELECT dtp.table_name, dtp.partition_name, dtp.num_rows
  FROM dba_tab_partitions dtp
 WHERE	   dtp.table_name = 'RAM_SLOW_PART_TAB2'
       AND dtp.partition_name IN ('RSLP2_SEP_2017',
				  'RSLP2_OCT_2017',
				  'RSLP2_NOV_2017',
				  'RSLP2_DEC_2017',
				  'RSLP2_MAX_PART');

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS        
------------------------------ ------------------------------ ----------        
RAM_SLOW_PART_TAB2             RSLP2_OCT_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_NOV_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_SEP_2017                          0        
RAM_SLOW_PART_TAB2             RSLP2_MAX_PART                          0        

4 rows selected.

Elapsed: 00:00:01.41

-- Perform 3rd Split

ALTER TABLE RAM_SLOW_PART_TAB2
   SPLIT PARTITION RSLP2_MAX_PART
      AT (TO_DATE ('2018-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
      INTO (PARTITION RSLP2_DEC_2017, PARTITION RSLP2_MAX_PART);

Table altered.

Elapsed: 00:00:01.68

-- Partition statistics after 3rd split

SELECT dtp.table_name, dtp.partition_name, dtp.num_rows
  FROM dba_tab_partitions dtp
 WHERE	   dtp.table_name = 'RAM_SLOW_PART_TAB2'
       AND dtp.partition_name IN ('RSLP2_SEP_2017',
				  'RSLP2_OCT_2017',
				  'RSLP2_NOV_2017',
				  'RSLP2_DEC_2017',
				  'RSLP2_MAX_PART');

TABLE_NAME                     PARTITION_NAME                   NUM_ROWS        
------------------------------ ------------------------------ ----------        
RAM_SLOW_PART_TAB2             RSLP2_OCT_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_NOV_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_DEC_2017                                   
RAM_SLOW_PART_TAB2             RSLP2_SEP_2017                          0        
RAM_SLOW_PART_TAB2             RSLP2_MAX_PART                                   

5 rows selected.

Elapsed: 00:00:00.09

In short, to perform a fast SPLIT PARTITION operation, ensure statistics are made available to database engine for the partition to be split and on indexes of the table when splitting a partition.

Leave a Comment

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.