分区分类
按照数据分区的规则,分为三大类:
hash/key
range/range columns
list/list columns
按照分区划分的维度。可以分为:
一级分区
二级分区
一级分区只有一个分区键,二级分区有两个分区键。
如图按照两个分区键user_id, create_time进行分区。
Hash分区
Hash分区需要指定分区键和分区个数。通过hash的分区表达式计算得到一个int类型的结果,这个结果再跟分区个数取模得到具体这行数据属于那个分区。通常用于给定分区键的点查询,例如按照用户id来分区。hash分区通常能消除热点查询。举个例子:
create table t1 (c1 int, c2 int) partition by hash(c1 + 1) partitions 5
其中,partition by hash(c1+1)
指定了分区键c1和分区表达式c1 + 1
,partitions 5指定了分区数。
对于(1,2)这行数据来说,它的属于(1 + 1) % 5 = 2号分区。
hash分区的限制和要求:
分区表达式的结果必须是int类型。
不能写向量,例如:
partition by hash(c1, c2)
。
Key分区
key分区跟hash分区类似,也是通过对分区个数取模的方式来确定数据属于哪个分区。不同的是系统会对key分区键做一个内部默认默认的hash函数后再取模。所以用户通常没有办法自己通过简单的计算来得知某一行属于哪个分区。举个例子:
create table t1 (c1 int, c2 int) partition by key(c1) partitions 5
OceanBase的hash函数对于非字符串类型,直接使用murmur hash。对于字符串类型,例如varchar和char类型。key分区使用的是MySQL的hash函数。这里主要是和字符串的collation相关,例如在某些collation里面大小写是相等的。例如’A’ = ‘a’,所以要求’A’和’a’计算的hash值需要一样。所以不能直接用murmurhash。必须使用MySQL的函数。这种情况我们测试发现MySQL的key分区的hash函数不太均匀。
key分区不要求是int类型,可以是任意类型。
key分区不能写表达式。
key分区支持向量。
key分区有一个特殊的语法:
create table t1 (c1 int primary key, c2 int) partition by key() partitions 5
- key分区list不写任何column,表示key分区的列是主键。
hash和key分区的对比:
- hash分区可以写表达式, key分区不行。
Range分区
range分区是按照分区表达式的范围来划分分区。通常用于对分区键需要按照范围的查询。例如通过按照时间字段进行范围分区,还有价格区间等一些分区方式。
create table t1 (c1 int, c2 int) partition by range(c1) (partition p0 values less than(100), partition p1 values less than(500), partitions p2 values less than(maxvalue));
p0, p1, p2 表示range的访问分别是(min, 100), [100, 500), [500, max) 这样一个范围。
range分区的限制和要求:
分区表达式的结果可以是int类型或datatime类型。
不能写向量,例如partition by range(c1, c2)
Range columns分区
range columns和range的区别:
range columns分区不要求是int类型,可以是任意类型。
range columns分区不能写表达式。
range columns分区支持向量。
Range分区的分区操作
目前提供对range分区的分区操作功能,能add/drop分区。add分区现在只能加在最后,所以最后不能是maxvalue的分区。如果是maxvalue的分区要增加一个分区,只能做分区分裂。现在还不支持分区分裂。
List分区
list分区是根据枚举类型的值来划分分区的。主要用于枚举类型
create table t1 (c1 int, c2 int) partition by list(c1) (partition p0 values in (1,2,3), partition p1 values in (5, 6), partition p2 values in (default));
这个表分区的含义是当某一行的c1 = 1 or c1 = 2 or c1 = 3
的时候,那么这一行属于分区p0,当c1 = 5 or c1 = 6
的时候,那么这一行属于分区p1。除此之外都所有行都属于p2。
list分区的限制和要求:
分区表达式的结果必须是int类型。
不能写向量,例如:
partition by list(c1, c2)
。
List columns分区
list columns和list的区别是
list columns分区不要求是int类型,可以是任意类型
list columns分区不能写表达式
list columns分区支持向量
二级分区
按照两个维度来把数据拆分成分区。最常用的地方就是类似用户账单领域,会按照user_id做hash分区,按照账单创建时间做range分区。
hash/key + range/range columns分区
range/range columns + hash/key分区
list + range/range columns 分区
range/range columns + list分区
hash/key + list分区
list+hash/key分区
说明
注意: Oracle的二级分区支持每个一级分区的二级分区分区定义不一样。支持类似 create table t1 (c1 int, c2 int) partition by range(c1) subpartition by hash(c2) (partition p0 values less than(100) (subpartition sp0), partition p1 values less than(200) (subpartition sp2, subpartition sp3)); 一级分区p0下面有一个分区,而一级分区p1下面有两个分区。 OceanBase暂时不支持这样的分区方式,必须用template的分区方式。这导致对于range分区的分区操作add/drop,必须是range分区做为一级分区的方式。所以强烈建议用range + hash的分区方式,而不是hash + range