oralce hash 分区

来源:互联网 发布:美食杰网站seo分析 编辑:程序博客网 时间:2024/05/02 00:42

  语法看起来比range复杂,其实使用起来比range更简单,这里需要我们指定的有:

  l column:分区依赖列(支持多个,中间以逗号分隔);

  l partition:指定分区,有两种方式:

  n 直接指定分区名,分区所在表空间等信息

  n 只指定分区数量,和可供使用的表空间。

CREATE TABLE DIV_INCOME_201011(
  CUST_ID              VARCHAR2(20),
  BAK_COL19          VARCHAR2(100),
  BAK_COL20          VARCHAR2(100)
) PARTITION BY HASH(CUST_ID) partitions 16 tablespace QFDATA;

 

 

   Global索引hash分区

  Hash分区索引的子句与hash分区表的创建子句完全相同,例如:

   create index idx_part_hash_id on t_partition_hash(id)
   global partition by hash(id)
   partitions 3 store in(tbspart01,tbspart02,tbspart03);

  索引已创建。

  查询索引的分区信息也仍是通过user_part_indexes、user_ind_partitions两个数据字典,不再举例。

  创建Local索引

  在前面学习range分区时,我们已经对Local索引的特性做了非常清晰的概述,因此这里也不再举例,如有疑问,建议再仔细复习range分区的相关示例,如果还有疑问,当面问我好了:)

  综上:

  Ø 对于global索引分区而言,在10g中只能支持range分区和hash分区,因此后续示例中不会再提及。

  Ø 对于local索引分区而言,其分区形式完全依赖于索引所在表的分区形式,不管从创建语法还是理解难度均无技术含量,因此后续也不再提供示例。

  Ø 注意,在创建索引时如果不显式指定global或local,则默认是global。

  Ø 注意,在创建global索引时如果不显式指定分区子句,则默认不分区(废话)。

 

hash partition是hash在数据库中一个简单的应用,虽然它没有range partition那么常用,但是我们在做数据库水平拆分时,其实就是利用了hash partition的原理,利用hash函数对某个key进行运算,然后将其分布到不同的主机上,原理很简单。

我们在设计时遇到了一个问题,当分区的数量需要变化时,基于hash的原理,数据可能会从一个分区移动到另外一个分区,因为某个key在4个分区时,可能被分布在分区3,而在8个分区时,可能被分布在分区5。这样每当分区数量变化时,就需要全部重新分布数据,代价很高。

那么Oracle是怎么做的?首先可以肯定的是Oracle的hash partition在分区增加时,不需要做全部数据的重新分布。有人告诉我Oracle的hash函数比较牛,可以保证分区数量增加时,这个hash函数可以让原来的数据还在旧的分区中,而新的数据可以分布在新的分区。Oracle的函数无非就是get_hash_value或ora_hash(10g),从hash的原理上来说,这也是不可能做到的。

我们对hash partition都有一个常识,就是partition的数量最好是2的次方,也就是2,4,8,16……,否则分区会出现不分区均衡的现象,按照hash的原理,不管是几个分区,都可以做到完全均衡的,为什么会不均衡,其实答案已经出来了,Oracle为了能够增加分区,为你预留了几个看不到的分区。
Oracle如何做到分区数量增加后,其他分区的数据不受影响呢,其实很简单,Oracle在做hash运算时,预留了分区,比如6个分区,实际上是用8个分区的hash来运算的,只不过把缺少的分区的数据合并到其他分区,这样就会出现数据不均衡的情况。Oracle的公式是这样的,用等于或者大于当前分区数量的最小的一个2的N次方,比如6个分区做8个hash bucket。我们再来考虑一下2,4,8,16(2的N次方)的情况,比如要把4个分区加为5个分区,因为已经是2的N次方,所以数据会均匀分布,而且Oracle还是使用4个hash bucket。这时新增的分区5实际上把分区1 split后产生的,这时因为有5个分区了,所以会使用8个hash bucket。这时Oracle的hash函数就比较牛了,它可以保证2,4,8,16个分区时,同一个键值分布在相同的分区或者是对应可以合并的分区,看下面的SQL:

select ora_hash(‘hellodba’,1)+1 par2,ora_hash(‘hellodba’,3)+1 par4,ora_hash(‘hellodba’,7)+1 par8,ora_hash(‘hellodba’,15)+1 par16 from dual;

      PAR2       PAR4       PAR8      PAR16
---------- ---------- ---------- ----------
         2          4          4         12
上面的SQL我们看到分区的数量在2,4,8,16时,hellodba这个key分别落在在2,4,4,12号分区,虽然落在不同的分区上,但是分区4和分区12是对应可合并的,这样就保证了数据是不需要移动的。一句话总结就是hash bucket总是2的N次方,如果分区数不足,则会合并数据,产生不均衡的情况,这样增加分区时,只需要对应分区的数据做split即可。同理,减少分区也不是简单的drop,而是合并分区。

再回到我们的项目中,我们为了解决这个问题,采用了更简单的处理方案,直接就做了1024个分区,我们有8个物理数据库,每个数据库中有128个表,以后再分拆时,只要移动这些表,并修改应用中的对应关系就可以了。其实和Oracle合并再拆分的思路是一样的。

原创粉丝点击