Home > Software engineering >  Why Is Oracle Failing to Round Robin Partitons When Using "Store In"?
Why Is Oracle Failing to Round Robin Partitons When Using "Store In"?

Time:12-14

Working with Oracle Database 19c. I'm currently trying to take an existing interval range partitioned table (partitioned by day) that was previously only storing partitions in a single tablespace and spread new partitions on to multiple tablespaces instead.

I executed the following to alter the table:

alter table TABLE_NAME set STORE IN(TABLESPACE_1, TABLESPACE_2, TABLESPACE_3)

This worked fine till I re-enabled our clean up script that drops partitions older than N days. Once I started deleting partitions, the Round Robing distribution would stop; new partitions would continue to get created in the same tablespace as the previous one.

I was able to resolve the issue by creating a sort of anchor read only partition that never gets droped from the oldest partition in the table. I'm trying to figure out why this 'anchor' partition is needed and how I can look under the hood to find the cause of this?

Here's an example of what I'm seeing I couldn't get my hands on a demo of this in 19C but ran this in 18c and seeing the same behavor.

create table rr_test (stringCol VARCHAR2(19 BYTE), UP TIMESTAMP(6)) tablespace ROUND_ROBIN_TEST1 
partition by range (UP) interval (numtodsinterval(1, 'DAY')) 
subpartition by LIST (stringCol) subpartition template 
(SUBPARTITION "STR01" VALUES ('01'), SUBPARTITION "STR02" values ('02')) (partition P1 values less than (timestamp '2021-07-21 00:00:00'));

INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-21 00:00:00');
INSERT into rr_test VALUES('02', TIMESTAMP '2021-09-22 00:00:00');
INSERT into rr_test VALUES('02', TIMESTAMP '2021-09-23 00:00:00');


alter table rr_test set store in (ROUND_ROBIN_TEST1, ROUND_ROBIN_TEST2, ROUND_ROBIN_TEST3);

INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-24 00:00:00');
INSERT into rr_test VALUES('02', TIMESTAMP '2021-09-25 00:00:00');
INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-26 00:00:00');


alter table rr_test drop partition P1;

INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-27 00:00:00');
alter table rr_test drop partition for (TIMESTAMP'2021-09-20 00:00:00');
INSERT into rr_test VALUES('02', TIMESTAMP '2021-09-28 00:00:00');
alter table rr_test drop partition for (TIMESTAMP'2021-09-21 00:00:00');
INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-29 00:00:00');


select * from user_tab_partitions where table_name = 'RR_TEST';

From the resutls, you can see that the last partitions to get created once we start dropping partitions causes the round robin distribution to stop.

RR_TEST SYS_P9280   TIMESTAMP' 2021-09-24 00:00:00' ROUND_ROBIN_TEST1
RR_TEST SYS_P9283   TIMESTAMP' 2021-09-25 00:00:00' ROUND_ROBIN_TEST1
RR_TEST SYS_P9286   TIMESTAMP' 2021-09-26 00:00:00' ROUND_ROBIN_TEST2
RR_TEST SYS_P9289   TIMESTAMP' 2021-09-27 00:00:00' ROUND_ROBIN_TEST3
RR_TEST SYS_P9292   TIMESTAMP' 2021-09-28 00:00:00' ROUND_ROBIN_TEST1
RR_TEST SYS_P9295   TIMESTAMP' 2021-09-29 00:00:00' ROUND_ROBIN_TEST1
RR_TEST SYS_P9298   TIMESTAMP' 2021-09-30 00:00:00' ROUND_ROBIN_TEST1

CodePudding user response:

Can you build a test case showing what you are observing? Here is mine, and it seems fine

SQL> create table t
  2  partition by range( dte )
  3  interval( numtodsinterval(1,'DAY') )
  4  store in ( users,asktom,largets)
  5  ( partition p1 values less than (  date '2020-01-01' ) )
  6  as
  7  select
  8    rownum pk,
  9    'name'||rownum data,
 10    date '2020-01-01'   rownum/1000 dte
 11  from dual
 12  connect by level <= 1000*10;

Table created.

SQL>
SQL> select count(*) from t;

  COUNT(*)
----------
     10000

1 row selected.

SQL>
SQL>
SQL> select partition_name, tablespace_name
  2  from user_tab_partitions
  3  where table_name = 'T'
  4  order by partition_position;

PARTITION_NAME                 TABLESPACE_NAME
------------------------------ --------------------
P1                             USERS
SYS_P68092                     ASKTOM
SYS_P68093                     LARGETS
SYS_P68094                     USERS
SYS_P68095                     ASKTOM
SYS_P68096                     LARGETS
SYS_P68097                     USERS
SYS_P68098                     ASKTOM
SYS_P68099                     LARGETS
SYS_P68100                     USERS
SYS_P68101                     ASKTOM
SYS_P68102                     LARGETS

12 rows selected.

SQL> alter table t drop partition P1;

Table altered.

SQL> alter table t drop partition SYS_P68092;

Table altered.

SQL> alter table t drop partition SYS_P68093;

Table altered.

SQL> alter table t drop partition SYS_P68094;

Table altered.

SQL> alter table t drop partition SYS_P68095;

Table altered.

SQL> alter table t drop partition SYS_P68096;

Table altered.

SQL> alter table t drop partition SYS_P68097;

Table altered.

SQL> alter table t drop partition SYS_P68098;

Table altered.

SQL> select partition_name, tablespace_name
  2  from user_tab_partitions
  3  where table_name = 'T'
  4  order by partition_position;

PARTITION_NAME                 TABLESPACE_NAME
------------------------------ --------------------
SYS_P68099                     LARGETS
SYS_P68100                     USERS
SYS_P68101                     ASKTOM
SYS_P68102                     LARGETS

4 rows selected.

SQL> select max(dte) from t;

MAX(DTE)
---------
11-JAN-20

1 row selected.

SQL> insert into t
  2  select
  3    rownum pk,
  4    'name'||rownum data,
  5    date '2020-01-12'   rownum/1000 dte
  6  from dual
  7  connect by level <= 1000*10;

10000 rows created.

SQL>
SQL>
SQL> select partition_name, tablespace_name
  2  from user_tab_partitions
  3  where table_name = 'T'
  4  order by partition_position;

PARTITION_NAME                 TABLESPACE_NAME
------------------------------ --------------------
SYS_P68099                     LARGETS
SYS_P68100                     USERS
SYS_P68101                     ASKTOM
SYS_P68102                     LARGETS
SYS_P68103                     ASKTOM
SYS_P68104                     LARGETS
SYS_P68105                     USERS
SYS_P68106                     ASKTOM
SYS_P68107                     LARGETS
SYS_P68108                     USERS
SYS_P68109                     ASKTOM
SYS_P68110                     LARGETS
SYS_P68111                     USERS
SYS_P68112                     ASKTOM
SYS_P68113                     LARGETS

15 rows selected.

CodePudding user response:

Addenda:

You can get into a "not round-robin-ing" issue if you are obeying a strict "add one, drop one" model because once we drop a partition (and you've dropped the anchor), we do a "reset", ie, the following partition starts from the first tablespace listed in the STORE IN clause. Because without the anchor, any given partition that remains could have been any of the tablespaces, so we can't really rely upon it to be an indicator of which should be the "next" tablespace to use.

For example, notice the STORE IN here is TS3, TS1, TS2

SQL> create table rr_test (stringCol VARCHAR2(19 BYTE), UP TIMESTAMP(6))
  2  tablespace TS1
  3  partition by range (UP) interval (numtodsinterval(1, 'DAY'))
  4  store in (TS3, TS1, TS2 )
  5  (partition P1 values less than (timestamp '2021-07-21 00:00:00'));

Table created.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-21 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-22 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-23 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-24 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-25 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-26 00:00:00');

1 row created.

SQL>
SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 P1                             TS1
                 2 SYS_P68275                     TS3
                 3 SYS_P68276                     TS1
                 4 SYS_P68277                     TS2
                 5 SYS_P68278                     TS3
                 6 SYS_P68279                     TS1
                 7 SYS_P68280                     TS2

7 rows selected.

SQL>
SQL> alter table rr_test drop partition P1;

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68275                     TS3
                 2 SYS_P68276                     TS1
                 3 SYS_P68277                     TS2
                 4 SYS_P68278                     TS3
                 5 SYS_P68279                     TS1
                 6 SYS_P68280                     TS2

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-27 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68275                     TS3
                 2 SYS_P68276                     TS1
                 3 SYS_P68277                     TS2
                 4 SYS_P68278                     TS3
                 5 SYS_P68279                     TS1
                 6 SYS_P68280                     TS2
                 7 SYS_P68281                     TS3

7 rows selected.

SQL>
SQL> alter table rr_test drop partition for (TIMESTAMP'2021-09-20 00:00:00');

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68276                     TS1
                 2 SYS_P68277                     TS2
                 3 SYS_P68278                     TS3
                 4 SYS_P68279                     TS1
                 5 SYS_P68280                     TS2
                 6 SYS_P68281                     TS3

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-28 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68276                     TS1
                 2 SYS_P68277                     TS2
                 3 SYS_P68278                     TS3
                 4 SYS_P68279                     TS1
                 5 SYS_P68280                     TS2
                 6 SYS_P68281                     TS3
                 7 SYS_P68282                     TS3

7 rows selected.

SQL>
SQL> alter table rr_test drop partition for (TIMESTAMP'2021-09-21 00:00:00');

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68277                     TS2
                 2 SYS_P68278                     TS3
                 3 SYS_P68279                     TS1
                 4 SYS_P68280                     TS2
                 5 SYS_P68281                     TS3
                 6 SYS_P68282                     TS3

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-29 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68277                     TS2
                 2 SYS_P68278                     TS3
                 3 SYS_P68279                     TS1
                 4 SYS_P68280                     TS2
                 5 SYS_P68281                     TS3
                 6 SYS_P68282                     TS3
                 7 SYS_P68283                     TS3

7 rows selected.

SQL>
SQL>
SQL>

Each time I drop a partition, I reset to the beginning of STORE IN and pick up TS3. Now the same but TS2 is listed as the first partition.

SQL>
SQL> create table rr_test (stringCol VARCHAR2(19 BYTE), UP TIMESTAMP(6))
  2  tablespace TS1
  3  partition by range (UP) interval (numtodsinterval(1, 'DAY'))
  4  store in (TS2, TS3, TS1 )
  5  (partition P1 values less than (timestamp '2021-07-21 00:00:00'));

Table created.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-21 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-22 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-23 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-24 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-25 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-26 00:00:00');

1 row created.

SQL>
SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 P1                             TS1
                 2 SYS_P68284                     TS2
                 3 SYS_P68285                     TS3
                 4 SYS_P68286                     TS1
                 5 SYS_P68287                     TS2
                 6 SYS_P68288                     TS3
                 7 SYS_P68289                     TS1

7 rows selected.

SQL>
SQL> alter table rr_test drop partition P1;

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68284                     TS2
                 2 SYS_P68285                     TS3
                 3 SYS_P68286                     TS1
                 4 SYS_P68287                     TS2
                 5 SYS_P68288                     TS3
                 6 SYS_P68289                     TS1

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-27 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68284                     TS2
                 2 SYS_P68285                     TS3
                 3 SYS_P68286                     TS1
                 4 SYS_P68287                     TS2
                 5 SYS_P68288                     TS3
                 6 SYS_P68289                     TS1
                 7 SYS_P68290                     TS2

7 rows selected.

SQL>
SQL> alter table rr_test drop partition for (TIMESTAMP'2021-09-20 00:00:00');

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68285                     TS3
                 2 SYS_P68286                     TS1
                 3 SYS_P68287                     TS2
                 4 SYS_P68288                     TS3
                 5 SYS_P68289                     TS1
                 6 SYS_P68290                     TS2

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-28 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68285                     TS3
                 2 SYS_P68286                     TS1
                 3 SYS_P68287                     TS2
                 4 SYS_P68288                     TS3
                 5 SYS_P68289                     TS1
                 6 SYS_P68290                     TS2
                 7 SYS_P68291                     TS2

7 rows selected.

SQL>
SQL> alter table rr_test drop partition for (TIMESTAMP'2021-09-21 00:00:00');

Table altered.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68286                     TS1
                 2 SYS_P68287                     TS2
                 3 SYS_P68288                     TS3
                 4 SYS_P68289                     TS1
                 5 SYS_P68290                     TS2
                 6 SYS_P68291                     TS2

6 rows selected.

SQL>
SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-29 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68286                     TS1
                 2 SYS_P68287                     TS2
                 3 SYS_P68288                     TS3
                 4 SYS_P68289                     TS1
                 5 SYS_P68290                     TS2
                 6 SYS_P68291                     TS2
                 7 SYS_P68292                     TS2

7 rows selected.

SQL>
SQL>

Then we resume round robin-ing as per normal with more data

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-09-30 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-10-01 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-10-02 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-10-03 00:00:00');

1 row created.

SQL> INSERT into rr_test VALUES('01', TIMESTAMP '2021-10-04 00:00:00');

1 row created.

SQL> select partition_position, partition_name, tablespace_name from user_tab_partitions where table_name = 'RR_TEST';

PARTITION_POSITION PARTITION_NAME                 TABLESPACE_NAME
------------------ ------------------------------ ------------------------
                 1 SYS_P68295                     USERS
                 2 SYS_P68296                     ASKTOM
                 3 SYS_P68297                     LARGETS
                 4 SYS_P68298                     USERS
                 5 SYS_P68299                     ASKTOM
                 6 SYS_P68300                     ASKTOM
                 7 SYS_P68301                     ASKTOM
                 8 SYS_P68302                     LARGETS
                 9 SYS_P68303                     USERS
                10 SYS_P68304                     ASKTOM
                11 SYS_P68305                     LARGETS
                12 SYS_P68306                     USERS

12 rows selected.

I'll log a bug anyway, because I suspect "drop-one-add-one" is a common use case.

  • Related