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

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

OracleHASH分區,沒有SPLIT PARTITION語言,替代的語句是ADD PARTITION。研究了一下發現ADD PARTITION語句和RANGELIST分區中的SPLIT PARTITION是十分相似的。


Oracle用於HASH分區的hash函數應該是唯一確定的,也就是說,給定分區個數,那麼分區鍵值在這些分區中的分佈就是固定不變的。否則的話,OracleHASH分區表就無法進行分區交換操作。

Oracle推薦分區數是2的冪,這樣可以保證各個分區的數據分佈相對均勻。其實對於分區數不是2的冪的HASH分區,可以看作是2的冪的一種變形。

首先考慮分區數是2的整數冪的情況:當Oracle的分區數從2個變爲4個,Oracle並不需要將所有數據重新打亂,而是將原有的2個分區每個都一分爲二。同樣的道理,如果將分區數設置爲8Oracle會將原有的4個分區一分爲二。

SQL> CREATE TABLE TEST_HASH2 (ID NUMBER) PARTITION BY HASH(ID)
2 (PARTITION P2_1, PARTITION P2_2);

表已創建。

SQL> CREATE TABLE TEST_HASH4 (ID NUMBER) PARTITION BY HASH(ID)
2 (PARTITION P4_1, PARTITION P4_2, PARTITION P4_3, PARTITION P4_4);

表已創建。

SQL> CREATE TABLE TEST_HASH8 (ID NUMBER) PARTITION BY HASH(ID)
2 (PARTITION P8_1, PARTITION P8_2, PARTITION P8_3, PARTITION P8_4,
3 PARTITION P8_5, PARTITION P8_6, PARTITION P8_7, PARTITION P8_8);

表已創建。

SQL> INSERT INTO TEST_HASH2 SELECT ROWNUM FROM USER_TABLES;

已創建22行。

SQL> INSERT INTO TEST_HASH4 SELECT ROWNUM FROM USER_TABLES;

已創建22行。

SQL> INSERT INTO TEST_HASH8 SELECT ROWNUM FROM USER_TABLES;

已創建22行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM TEST_HASH2 PARTITION(P2_1);

ID
----------
2
5
6
8
11
13
18
20
21

已選擇9行。

SQL> SELECT * FROM TEST_HASH4 PARTITION(P4_1);

ID
----------
6
11
13

SQL> SELECT * FROM TEST_HASH4 PARTITION(P4_3);

ID
----------
2
5
8
18
20
21

已選擇6行。

SQL> SELECT * FROM TEST_HASH8 PARTITION(P8_1);

ID
----------
6
11

SQL> SELECT * FROM TEST_HASH8 PARTITION(P8_5);

ID
----------
13

SQL> SELECT * FROM TEST_HASH8 PARTITION(P8_3);

ID
----------
5
21

SQL> SELECT * FROM TEST_HASH8 PARTITION(P8_7);

ID
----------
2
8
18
20

舉個形象一些的例子,OracleHASH分區就像是一棵大的二叉樹。每個分區就相當於二叉樹的一個葉節點。二叉樹的第一層,只有一個根節點,對應只有1個分區的情況。二叉樹的第二層,兩個葉節點,對應2個分區的情況。二叉樹的第三層,4個葉節點,對應4個分區的情況。二叉樹的第n層,2^(n-1)個葉節點,對應2^(n-1)個分區情況。

每個分區中包含的分區鍵值都來自它的上層枝節點。

而對於分區數爲非2的整數冪的情況,則可以看作上面的一種變形。可以看作樹的最底層葉節點沒有完全填滿,還保留了幾個上一層的葉節點。以6個分區爲例,可以看成一個42叉樹,第4層包括四個葉節點,第3層包括兩個葉節點。

上面說了這麼多,主要是爲了說明,OracleHASH分區在增加分區時,最多隻會影響到一個分區的數據。如果分區鍵值的分佈恰好在新增分區中不存在,那麼新增分區時,不會影響任何一個已經存在的分區。否則的話,只會影響它的上一層的枝節點分區。

Oracle首先會將本層的所有葉節點填滿,然後纔會增加新的一層。

Oracle在增加新的分區時,會根據HASH函數確定原有分區內的數據在兩個新分區內的分佈,增加完分區後,屬於新分區的數據已經從源分區中轉移到新分區中。

從二叉樹的模型來說,增加分區的過程相當於一個節點分裂成兩個葉節點的情況。左節點對應着分裂前的節點,而右節點就是新增的節點。

Oracle新增分區時,將從哪個分區中分裂出數據是可以判斷出來的。Oracle增加分區和分裂數據的分區都是按照順序進行的。

如果要增加的分區是第N個分區,大於等於N的最小2的整數冪爲M,則當增加第N個分區時,這個分區的數據來源於分區N-M/2

上面的公式過於抽象了,我們舉兩個具體的例子:

目前有4個分區,要增加第5個分區,大於等於5的最小整數冪是8,根據公式,5-8/2=1,5個分區的數據來源於分區1

目前有7個分區,要增加第8個分區,而大於等於8的最小整數冪也是8,根據公式,8-8/2=4,第8個分區的數據來源於分區4

下面驗證一下:

SQL> SELECT * FROM TEST_HASH4 PARTITION (P4_1);

ID
----------
6
11
13

SQL> ALTER TABLE TEST_HASH4 ADD PARTITION P4_5;

表已更改。

SQL> SELECT * FROM TEST_HASH4 PARTITION (P4_5);

ID
----------
13

SQL> CREATE TABLE TEST_HASH7 (ID) PARTITION BY HASH(ID)
2 (PARTITION P7_1, PARTITION P7_2, PARTITION P7_3, PARTITION P7_4,
3 PARTITION P7_5, PARTITION P7_6, PARTITION P7_7)
4 AS SELECT ROWNUM FROM USER_TABLES;

表已創建。

SQL> SELECT * FROM TEST_HASH7 PARTITION (P7_4);

ID
----------
1
3
4
7
14
15
16

已選擇7行。

SQL> ALTER TABLE TEST_HASH7 ADD PARTITION P7_8;

表已更改。

SQL> SELECT * FROM TEST_HASH7 PARTITION(P7_8);

ID
----------
1
7
14
15

SQL> SELECT * FROM TEST_HASH7 PARTITION (P7_4);

ID
----------
3
4
16

分區合併操作的算法相當於增加分區的逆向操作,這裏就不在描述了。

從上面的分析可以看出,HASH分區的ADD PARTITIONRANGE分區、LIST分區的SPLIT PARTITION很類似,都是從一個分區中取出一部分數據放到新增的分區中。唯一的區別在於,SPLIT操作允許用戶指定操作的分區和SPLIT的位置,而ADD PARTITION則完全由Oracle來確定了。

 

最後想說的是,上面嘗試用二叉樹的方式解釋分區的增加還是比較合適的,其實如果加上幾副圖的話,可能更容易把問題描述清楚。不過本文的實際意義並不大,在實際使用中沒有什麼的必要去了解新增分區數據來自哪個分區。所以,我也就不花力氣再去配圖了,有興趣的可以自己在腦子中想象一下。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章