Partial Indexes–Take Care With Truncate

connor_mc_d's picture

Partial indexes are a very cool feature that came along with Oracle 12c. The capability at partition level to control index existence allows for a couple of obvious use cases:

1) You index the data in recent partitions only, because small amounts of data are aggressively searched by applications and/or users, but not the older data because the queries for older data are either less frequent or are more analytical in nature.

2) You index the data in older partitions only, because you are putting the recent data into the in-memory store so almost any kind of access is very fast, but you do not want to swamp the entire in-memory store with older data that people rarely query.  But you still want reasonable access performance on that old data.

Whatever your use-case, there is currently an outstanding issue with partial indexes that you need to be aware of. (Note: This is not correct functionality and will be fixed in a future release). If you truncate a table, then the partial index dictionary definition may not be correctly observed for partitions.

Here’s an example:


SQL> create table t ( x int, y int )
  2  partition by range ( x )
  3  (
  4    partition p1 values less than ( 1000 ) indexing on,
  5    partition p2 values less than ( 2000 ) indexing off
  6  );
 
Table created.
 
SQL> insert into t
  2  select rownum, rownum from dual connect by level < 2000;
 
1999 rows created.
 
SQL> create index ix on t ( x ) local indexing partial;
 
Index created.
 
SQL> select segment_name, partition_name
  2  from user_segments
  3  where segment_name = 'IX';
 
SEGMENT_NAME                   PARTITION_NAME
------------------------------ ------------------------------
IX                             P1
 
SQL> select partition_name, status
  2  from user_ind_partitions
  3  where index_name = 'IX';
 
PARTITION_NAME                 STATUS
------------------------------ --------
P1                             USABLE
P2                             UNUSABLE

So far so good… partial indexing is working as expected. Then I truncate the table:


SQL> truncate table t;
 
Table truncated.
 
SQL>
SQL> select segment_name, partition_name
  2  from user_segments
  3  where segment_name = 'IX';
 
SEGMENT_NAME                   PARTITION_NAME
------------------------------ ------------------------------
IX                             P1
IX                             P2
 
SQL> select partition_name, status
  2  from user_ind_partitions
  3  where index_name = 'IX';
 
PARTITION_NAME                 STATUS
------------------------------ --------
P1                             USABLE
P2                             USABLE
 
SQL> select segment_name, partition_name
  2  from user_segments
  3  where segment_name = 'IX';
 
SEGMENT_NAME                   PARTITION_NAME
------------------------------ ------------------------------
IX                             P1
IX                             P2
 
SQL> select partition_name, status
  2  from user_ind_partitions
  3  where index_name = 'IX';
 
PARTITION_NAME                 STATUS
------------------------------ --------
P1                             USABLE
P2                             USABLE

And now we seem to have dropped our knowledge of partial indexing and the second index partition springs into existence. The dictionary for the table remains unaffected


SQL> select partition_name, indexing
  2  from   user_tab_partitions
  3  where  table_name = 'T';
 
PARTITION_NAME                 INDE
------------------------------ ----
P1                             ON
P2                             OFF

The workaround is easy. You simply re-issue the partial indexing command


SQL> alter table t modify partition p2 indexing off;

Table altered.

SQL>
SQL> select segment_name, partition_name
  2  from user_segments
  3  where segment_name = 'IX';

SEGMENT_NAME                   PARTITION_NAME
------------------------------ ---------------------------
IX                             P1

But obviously, you need to remember to do this.

To prevent automated spam submissions leave this field empty.