分区表概述
OceanBase数据库把普通的表的数据按照一定的规则划分到不同的区块内,同一区块的数据物理上存储在一起。这种划分区块的表叫做分区表,其中的每一个区块称作分区。分区技术是非常重要的分布式能力之一,它能解决大表的容量问题和并发访问时性能问题。普通的表只有一个分区,可以看作分区表的特例。每个分区只能存在于一个节点内部,分区表的不同分区可以分散在不同节点上。
创建分区的目的是为了在特定的SQL操作中减少数据读写的总量以减少响应时间:
可扩展性,可管理性,提高性能
OceanBase分区表特点
可多机扩展
提高可管理性
提高性能
自动负载均衡、自动容灾
对业务透明,可以取代“分库分表”方案
支持分区间并行
单表分区个数最大8192
单机partition支持上限: 8万(推荐不超过3万)
OceanBase分区表
分为一级分区和二级分区
OB现在支持的一级分区类型有:HASH,KEY,LIST,RANGE,RANGE COLUMNS,生成列分区
二级分区相当于在一级分区的基础上,又从第二个维度进行了拆分
MySQL模式:
RANGE分区,NGE COLUMNS 分区,LIST 分区,LIST COLUMNS 分区,HASH 分区,KEY 分区,组合分区
Oracle 模式:
RANGE 分区,LIST 分区,HASH 分区,组合分区
HASH 分区
一级分区
HASH分区需要指定分区键和分区个数,适合于对不能用 Range 分区、List 分区方法的场景。通过对分区键上的Hash函数值来散列记录到不同分区中。通常用于给定分区键的点查询,例如按照用户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指定了分区数
OB MySQL模式的Hash分区限制和要求:
分区表达式的结果必须是int类型。
不能写向量,例如partition by hash(c1, c2)
KEY 分区
一级分区
KEY分区与HASH分区类似,也是通过对分区个数取模的方式来确定数据属于哪个分区,不同在于:
系统会对Key分区键做一个内部默认的Hash函数后再取模
用户通常没有办法自己通过简单的计算来得知某一行属于哪个分区
测试发现KEY分区所用到的HASH函数不太均匀
create table t1 (c1 varchar(16), c2 int) partition by key(c1) partitions 5
KEY分区不要求是int类型,可以是任意类型
KEY分区不能写表达式(与HASH分区区别)
KEY分区支持向量
KEY分区有一个特殊的语法
create table t1 (c1 int primary key, c2 int) partition by key() partitions 5
KEY分区分区键不写任何column,表示key分区的列是主键
LIST 分区
一级分区
LIST分区是根据枚举类型的值来划分分区的,主要用于枚举类型
LIST分区的限制和要求
分区表达式的结果必须是int类型
不能写向量,例如partition by list(c1, c2)
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));
List columns 和 list 的区别是:
list columns分区不要求是int类型,可以是任意类型
list columns分区不能写表达式
list columns分区支持向量
RANGE 分区
一级分区
RANGE分区是按用户指定的表达式范围将每一条记录划分到不同分区
常用场景: 按时间字段进行分区
目前提供对range分区的分区操作功能,能add/drop分区
存在maxvalue的分区的情况,由于add分区现在只能加在最后,所以会添加分区失败
不存在maxvalue的分区的情况,当插入的数据超出当前分区的最大值,则会插入失败。
CREATE TABLE `info_t`(id INT, gmt_create TIMESTAMP, info VARCHAR(20), PRIMARY KEY (gmt_create)) PARTITION BY RANGE(UNIX_TIMESTAMP(gmt_create)) (PARTITION p0 VALUES LESS THAN (UNIX_TIMESTAMP('2015-01-01 00:00:00')), PARTITION p1 VALUES LESS THAN (UNIX_TIMESTAMP('2016-01-01 00:00:00')), PARTITION p2 VALUES LESS THAN (UNIX_TIMESTAMP('2017-01-01 00:00:00')));
RANGE COLUMNS 分区
一级分区
RANGE COLUMNS分区与RANGE分区类似,但不同点在于RANGE COLUMNS分区可以按一个或多个分区键向量进行分区,并且每个分区键的类型除了INT类型还可以支持其他类型,比如VARCHAR、DATETIME等
RANGE COLUMNS和RANGE的区别是
1. RANGE COLUMNS分区不要求是int类型,可以是任意类型
2. RANGE COLUMNS分区不能写表达式
3. RANGE COLUMNS分区支持向量
生成列分区
一级分区
生成列是指这一列是由其他列计算而得
生成列分区是指将生成列作为分区键进行分区,该功能能够更好的满足期望将某些字段进行一定处理后作为分区键的需求(比如提取一个字段的一部分,作为分区键)
CREATE TABLE gc_part_t(t_key varchar(10) PRIMARY KEY, gc_user_id VARCHAR(4) GENERATED ALWAYS AS (SUBSTRING(t_key, 1, 4)) VIRTUAL, c3 INT) PARTITION BY KEY(gc_user_id) PARTITIONS 10;
二级分区
二级分区是指按照两个维度来把数据拆分成分区。最常用的地方就是类似用户账单领域,会按照user_id做HASH分区,按照账单创建时间做RANGE分区
示例:按两个维度划分数据:
CREATE TABLE history_t (user_id INT, gmt_create DATETIME, info VARCHAR(20), PRIMARY KEY(user_id, gmt_create)) PARTITION BY RANGE COLUMNS (gmt_create) SUBPARTITION BY HASH(user_id) SUBPARTITIONS 3 (PARTITION p0 VALUES LESS THAN ('2014-11-11'), PARTITION p1 VALUES LESS THAN ('2015-11-11'), PARTITION p2 VALUES LESS THAN ('2016-11-11'), PARTITION p3 VALUES LESS THAN ('2017-11-11') );
二级分区支持的分区方式
二级分区支持的分区方式
HASH/KEY + RANGE/RANGE_COLUMNS 分区
RANGE/RANGE_COLUMNS + HASH/KEY 分区
LIST/LIST_COLUMNS+ RANGE/RANGE_COLUMNS 分区
RANGE/RANGE_COLUMNS + LIST/LIST_COLUMNS分区
HASH/KEY + LIST/LIST_COLUMNS 分区
LIST/LIST_COLUMNS+HASH/KEY 分区
对于RANGE分区的分区操作add/drop,必须是RANGE分区作为一级分区的方式。所以强烈建议用RANGE + HASH的分区方式,而不是HASH + RANGE。
分区管理
增加分区
伴随数据量增长,range分区需要能够扩展 -> ADD PARTITION
语法: ALTER TABLE ... ADD PARTITION
ALTER TABLE members ADD PARTITION(PARTITION p3 VALUES LESS THAN(2000));
删除分区
对于按时间范围分区的表,有时需要作过期数据清理 -> DROP PARTITION
语法: ALTER TABLE ... DROP PARTITION
ALTER TABLE members DROP PARTITION(P3);
使用限制
只有range分区,可以删除任意一个一级range分区
只能以append方式往后添加分区,也就是说,新加分区的range value总是最大的
分区选择和分区裁剪
表结构
create table t2(c1 int primary key, c2 int, c3 int) partition by hash(c1) partitions 5;
分区选择
explain select * from t1 partition(p4);
分区裁剪
explain select * from t2 where c1 = 5 or c1 = 4;
一级分区裁剪的基本原理-Hash/List 分区
分区裁剪就是根据 where 子句里面的条件并且计算得到分区列的值,然后通过结果判断需要访问哪些分区如果分区函数为表达式,且该表达式作为一个整体出现在等值条件里,也可以做分区裁剪
一级分区裁剪的基本原理-Range分区
通过where子句的分区键的范围跟表定义的分区范围的交集来确定需要访问的分区
对于Range分区,因为考虑到函数单调性,如果分区表达式是一个函数并且查询条件是一个范围,则不支持分区裁剪
二级分区裁剪的基本原理
对于二级分区,先按照一级分区键确定一级需要访问的分区,然后在通过二级分区键确定二级分区需要访问的分区。然后做一个乘积确定二级分区访问的所有物理分区。
分区表的使用建议
业务形态(热点数据打散、历史数据维护便利性、业务SQL的条件形态(分区裁剪)
OB各种分区类型的设置要求
分区键必须是主键的子集
Range分区,最后一个不能是maxvalue
考虑分区裁剪、partition wise join优化
Leader binding\Tablegroup
为了避免写入放大问题,选择表的自定义主键时,不要使用随机生成的值,要尽量有序,比如时序递增的。
分区个数:单机分区上限、单机租户允许创建的最大分区数量上限、单表分区数上限