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来确定了。

 

最后想说的是,上面尝试用二叉树的方式解释分区的增加还是比较合适的,其实如果加上几副图的话,可能更容易把问题描述清楚。不过本文的实际意义并不大,在实际使用中没有什么的必要去了解新增分区数据来自哪个分区。所以,我也就不花力气再去配图了,有兴趣的可以自己在脑子中想象一下。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值