HASH分區新增分區對索引狀態的影響 – JAVA編程語言程序開發技術文章

一直認為Oracle對於所有分區的操作都是一樣的,隻有數據的改變才會導致分區狀態的失效,沒想到HASH分區的實現方式並不相同。

HASH分區表增加新的分區的一點研究:

 

看一個范圍分區SPLIT的例子:

SQL> CREATE TABLE T_PART
 2 (ID NUMBER, NAME VARCHAR2(30))
 3 PARTITION BY RANGE (ID)
 4 (PARTITION P1 VALUES LESS THAN (10),
 5 PARTITION PMAX VALUES LESS THAN (MAXVALUE));

Table created.

SQL> INSERT INTO T_PART
 2 SELECT ROWNUM, TNAME
 3 FROM TAB;

12 rows created.

SQL> CREATE INDEX IND_T_PART_ID ON T_PART(ID) LOCAL;

Index created.tb

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_PART_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_PART_ID                  P1                             USABLE
IND_T_PART_ID                  PMAX                           USABLE

SQL> SELECT COUNT(*) FROM T_PART PARTITION (PMAX);

 COUNT(*)
———-
         3

SQL> ALTER TABLE T_PART SPLIT PARTITION PMAX AT (20)
 2 INTO (PARTITION P2, PARTITION P3);

Table altered.

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_PART_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_PART_ID                  P2                             USABLE
IND_T_PART_ID                  P3                             USABLE
IND_T_PART_ID                  P1                             USABLE

可以看到,對於范圍分區而言,即使是SPLIT包含數據的分區,隻要沒有真正導致數據發生變化,就不會導致索引的失效。這裡將PMAX分區SPLIT成P2和P3兩個分區,其中PMAX中的所有數據都進入P2分區,而P3分區為空,這種情況下沒有數據的改變,因此所有分區索引的狀態都不會變為UNUSABLE。

但是HASH分區的ADD PARTITION並沒有遵守這個規則,事實上對於每次ADD分區,都會導致一個分區的數據發生分裂,而分裂的結果不管原分區的數據是否發生變化,都會導致原分區索引狀態變為UNUSABLE,至於新增分區的索引狀態,則取決於是否有數據的改變。

SQL> CREATE TABLE T_HASH
 2 (ID NUMBER)
 3 PARTITION BY HASH (ID)
 4 (PARTITION P1,
 5 PARTITION P2,
 6 PARTITION P3,
 7 PARTITION P4);

Table created.

SQL> CREATE INDEX IND_T_HASH_ID ON T_HASH(ID) LOCAL;

Index created.

SQL> INSERT INTO T_HASH SELECT ROWNUM FROM TAB;

12 rows created.

SQL> COMMIT;

Commit complete.

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_HASH_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_HASH_ID                  P1                             USABLE
IND_T_HASH_ID                  P2                             USABLE
IND_T_HASH_ID                  P3                             USABLE
IND_T_HASH_ID                  P4                             USABLE

SQL> SELECT * FROM T_HASH PARTITION (P1);

        ID
———-
         6
        11

SQL> SELECT * FROM T_HASH PARTITION (P2);

        ID
———-
         9
        10
        12

SQL> SELECT * FROM T_HASH PARTITION (P3);

        ID
———-
         2
         5
         8

SQL> SELECT * FROM T_HASH PARTITION (P4);

        ID
———-
         1
         3
         4
         7

下面新增一個PARTITION P5:

SQL> ALTER TABLE T_HASH ADD PARTITION P5;

Table altered.

SQL> SELECT * FROM T_HASH PARTITION (P5);

no rows selected

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_HASH_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_HASH_ID                  P5                             USABLE
IND_T_HASH_ID                  P1                             UNUSABLE
IND_T_HASH_ID                  P2                             USABLE
IND_T_HASH_ID                  P3                            USABLE
IND_T_HASH_ID                  P4                             USABLE

新增的PARTITION P5中並沒有任何的數據,也就是說沒有任何的數據從P1遷移到P5中,但是查詢分區索引的狀態發現,P1對應的分區索引狀態已經變為UNUSABLE。這和范圍分區的處理方式完全不同。而P5分區由於沒有任何數據,因此分區狀態是USABLE。

SQL> ALTER TABLE T_HASH ADD PARTITION P6;

Table altered.

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_HASH_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_HASH_ID                  P5                             USABLE
IND_T_HASH_ID                  P6                             UNUSABLE
IND_T_HASH_ID                  P1                             UNUSABLE
IND_T_HASH_ID                  P2                             UNUSABLE
IND_T_HASH_ID                  P3                             USABLE
IND_T_HASH_ID                  P4                             USABLE

6 rows selected.

SQL> DELETE T_HASH WHERE ID = 5;       

1 row deleted.

SQL> COMMIT;

Commit complete.

SQL> ALTER TABLE T_HASH ADD PARTITION P7;

Table altered.

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_HASH_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_HASH_ID                  P5                             USABLE
IND_T_HASH_ID                  P6                             UNUSABLE
IND_T_HASH_ID                  P7                             UNUSABLE
IND_T_HASH_ID                  P1                             UNUSABLE
IND_T_HASH_ID                  P2                             UNUSABLE
IND_T_HASH_ID                  P3                             UNUSABLE
IND_T_HASH_ID                  P4                             USABLE

7 rows selected.

SQL> SELECT * FROM T_HASH PARTITION (P3);

no rows selected

SQL> SELECT * FROM T_HASH PARTITION (P7);

        ID
———-
         2
         8

為瞭更好的說明這個問題,在增加PARTITION P7之前,刪除瞭ID為5的記錄,這是增加分區後可以發現,原有的P3已經不包含任何的數據,全部的記錄都進入到新增的P7分區,但是無論是P3還是P7,狀態都是UNUSABLE。這證明瞭前面提到的,隻要是新增HASH分區,就會導致源分區索引狀態變為UNUSABLE,除非是一種情況:源分區本身就沒有數據:

SQL> ALTER TABLE T_HASH ADD PARTITION P8;

Table altered.

SQL> SELECT INDEX_NAME, PARTITION_NAME, STATUS                         
 2 FROM USER_IND_PARTITIONS
 3 WHERE INDEX_NAME = 'IND_T_HASH_ID';

INDEX_NAME                     PARTITION_NAME                 STATUS
—————————— —————————— ——–
IND_T_HASH_ID                  P5                             USABLE
IND_T_HASH_ID                  P6                             UNUSABLE
IND_T_HASH_ID                  P7                             UNUSABLE
IND_T_HASH_ID                  P1                             UNUSABLE
IND_T_HASH_ID                  P2                             UNUSABLE
IND_T_HASH_ID                  P3                             UNUSABLE
IND_T_HASH_ID                  P4                             USABLE
IND_T_HASH_ID                  P8                             USABLE

8 rows selected.

事實上,對於HASH分區的ADD PARTITION操作,Oracle基本上還是秉承瞭沒有數據變化就不會導致索引失效的思路。唯一的差別在於,對於源分區包含記錄的情況,Oracle並沒有最後去驗證,是否真的發生瞭數據的遷移。

發佈留言