GBase 8a数据库集群,从V9版本才支持分区功能,V8不支持分区。分区表是根据一定规则,将数据库中的一张表分解成多个更小的容易管理的部分,从逻辑上看,只有一张表,但底层却是由多个物理分区组成。分区表包括普通分区表和子分区表。
目录导航
参考
GBase 8a 元数据表介绍,分区information_schema.Partitions
GBase 8a 元数据表介绍
GBase 8a分区表指定特定分区的查询方法
GBase 8a数据库Range分区表null值保存分区位置测试
数据库版本
不同的版本可能功能有变动,如需要了解详情,请咨询数据库厂商当前最新版本的情况。本文也会尽量同步更新。
gbase> select @@version;
+-----------------+
| @@version |
+-----------------+
| 9.5.2.26.121440 |
+-----------------+
1 row in set (Elapsed: 00:00:00.00)
支持的分区类型
目前常用的分区方法有RANGE分区、LIST分区、KEY分区、HASH分区,在分区的管理上目前支持创建分区、添加分区、删除分区。
RANGE分区表和LIST分区表支持子分区,子分区的分区类型可以为[LINEAR] HASH和[LINEAR] KEY。
information_schema.partitions中可以查到所创建的分区表信息。
RANGE : 一个连续范围
LIST : 一个个的单独指定的值,可以不连续
KEY: 支持各种数据类型,比如字符串,的hash分类方式。
HASH: 针对数字的的hash
分区表支持分区列类型
数值型, 如: int, bigint, smallint, float 等
时间类型: date,datetime, time
支持分区函数
abs(), ceiling(), ceil(), datadiff(), day(), dayofmonth(), dayofweek(),dayofyear(), floor(), hour(), microsecond(), minute(), mod(),month(), quarter(), second(), time_to_sec(), to_days(), to_seconds(),weekday(), year(),yearweek(), +, -, *, /, div, %, extract(),from_days()
分区
range 分区
数字类型的range分区
gbase> create table p1(id int)
partition by range(id)(
partition p1 values less than (10),
partition po values less than MAXVALUE
);
Query OK, 0 rows affected (Elapsed: 00:00:02.29)
日期类型的RANGE分区
create table t_list_1(id int, name varchar(100),birth date)
partition by range(birth)
(
partition p1357_1980 values less than (to_date('1980-01-01','yyyy-mm-dd')),
partition p1357_2000 values less than (to_date('2000-01-01','yyyy-mm-dd')),
partition p1357_other values less than MAXVALUE
);
多列RANGE分区
当前版本尚不支持,但后续可能会实现。
gbase> create table t_range_multi(id int, name varchar(100),birth date)
-> partition by range(id,birth)
-> (
-> partition p1357_1980 values less than (10,to_date('1980-01-01','yyyy-mm-dd')),
-> partition p1357_2000 values less than (20,to_date('2000-01-01','yyyy-mm-dd')),
-> partition p1357_other values less than MAXVALUE
-> );
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your GBase server version for the right syntax to use near 'birth)
(
partition p1357_1980 values less than (10,to_date('1980-01-0' at line 2
gbase>
list分区
gbase> create table p2 (id int)
partition by list(id)(
partition a values in (1,3,5,7),
partition b values in (2,4,6,8)
);
Query OK, 0 rows affected (Elapsed: 00:00:00.61)
Key分区
如果没指定分区名字,则默认从p0开始,p0,p1,p2...。查询时可以用 partition(p0,p1)这样来指定分区。
int类型的key分区
create table t_key_int(id int, name varchar(100),birth date)
partition by key(id)
(
partition p01,
partition p02
);
gbase> create table t_key_int(id int, name varchar(100),birth date)
-> partition by key(id)
-> (
-> partition p01,
-> partition p02
-> );
Query OK, 0 rows affected (Elapsed: 00:00:00.16)
varchar类型的key分区
create table t_key_varchar(id int, name varchar(100),birth date)
partition by key(name)
(
partition p01,
partition p02
);
gbase> create table t_key_varchar(id int, name varchar(100),birth date)
-> partition by key(name)
-> (
-> partition p01,
-> partition p02
-> );
Query OK, 0 rows affected (Elapsed: 00:00:00.17)
date类型的key分区
create table t_key_date(id int, name varchar(100),birth date)
partition by key(birth)
(
partition p01,
partition p02
);
gbase> create table t_key_date(id int, name varchar(100),birth date)
-> partition by key(birth)
-> (
-> partition p01,
-> partition p02
-> );
Query OK, 0 rows affected (Elapsed: 00:00:00.42)
Hash分区
如果没指定分区名字,则默认从p0开始。查询时可以用 partition(p0,p1)这样来指定分区。
数字类型的hash分区
整数在内部,就是按照数字的mod值进行划分。比如10个节点,数字0保存在第1个分区,数字9保存在第10个分区。
create table t_hash_int(id int, name varchar(100),birth date)
partition by hash(id)
(
partition p01,
partition p02
);
gbase> create table t_hash_int(id int, name varchar(100),birth date)
-> partition by hash(id)
-> (
-> partition p01,
-> partition p02
-> );
Query OK, 0 rows affected (Elapsed: 00:00:00.17)
其它类型的hash分布不支持
gbase> create table t_hash_varchar(id int, name varchar(100),birth date)
-> partition by hash(name)
-> (
-> partition p01,
-> partition p02
-> );
ERROR 1702 (HY000): gcluster table error: The PARTITION function returns the wrong type.
gbase> create table t_hash_date(id int, name varchar(100),birth date)
-> partition by hash(birth)
-> (
-> partition p01,
-> partition p02
-> );
ERROR 1050 (42S01): Table 't_hash_date' already exists
gbase> drop table t_hash_date;
Query OK, 0 rows affected (Elapsed: 00:00:00.04)
gbase> create table t_hash_date(id int, name varchar(100),birth date)
-> partition by hash(birth)
-> (
-> partition p01,
-> partition p02
-> );
ERROR 1702 (HY000): gcluster table error: The PARTITION function returns the wrong type.
gbase>
PARTITIONS num 批量建立
批量生成一定的分区,不再指定分区名字,适合key和hash分区类型。
gbase> create table t_key_varchar(id int, name varchar(100),birth date)
-> partition by key(name)
-> PARTITIONS 10;
Query OK, 0 rows affected (Elapsed: 00:00:00.54)
子分区
key和hash不能再有子分区,只允许RANGE/LIST可以拥有子分区,包括hash/key子分区类型。
提示:当前集群版本,还不支持range-list这样的子分区格式,具体当前最新版本支持详情,还请咨询数据库厂商。
语法
PARTITION BY
{ RANGE(expr)
| LIST(expr)
| LINEAR] HASH(expr)
| [LINEAR] KEY(column_list)}
[PARTITIONS num]
[SUBPARTITION BY
{ [LINEAR] HASH(expr)
| [LINEAR] KEY(column_list) }
[SUBPARTITIONS num]
]
样例
如下是日期类型的Range分区带hash类型的子分区的例子。
create table t_list_2(id int, name varchar(100),birth date)
partition by range(birth)
subpartition by hash(id)
(
partition p1357_1980 values less than (to_date('1980-01-01','yyyy-mm-dd'))(
subpartition a1980,
subpartition b1980
),
partition p1357_2000 values less than (to_date('2000-01-01','yyyy-mm-dd'))(
subpartition a2000,
subpartition b2000
),
partition p1357_other values less than MAXVALUE(
subpartition aother,
subpartition bother
)
);
SUBPARTITIONS num 批量建立
对于key和hash的子分区,可以批量建立,不指定名字。
create table t_range_hash(id int, name varchar(100),birth date)
partition by range(birth)
subpartition by hash(id) subpartitions 2
(
partition p1357_1980 values less than (to_date('1980-01-01','yyyy-mm-dd')),
partition p1357_2000 values less than (to_date('2000-01-01','yyyy-mm-dd')),
partition p1357_other values less than MAXVALUE
);
增加分区
目前版本只有Range和List分区支持增加分区
gbase> show create table td;
CREATE TABLE "td" (
"id" int(11) DEFAULT NULL,
"d" date DEFAULT NULL
) ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace'
PARTITION BY RANGE (d)
(PARTITION p_20230307 VALUES LESS THAN (20230308) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS,
PARTITION p_20230308 VALUES LESS THAN (20230309) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS)
1 row in set (Elapsed: 00:00:00.01)
gbase> alter table td add partition(partition p_20230309 values less than (20300310));
Query OK, 0 rows affected (Elapsed: 00:00:00.28)
Records: 0 Duplicates: 0 Warnings: 0
gbase> show create table td;
CREATE TABLE "td" (
"id" int(11) DEFAULT NULL,
"d" date DEFAULT NULL
) ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace'
PARTITION BY RANGE (d)
(PARTITION p_20230307 VALUES LESS THAN (20230308) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS,
PARTITION p_20230308 VALUES LESS THAN (20230309) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS,
PARTITION p_20230309 VALUES LESS THAN (20300310) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS) |
1 row in set (Elapsed: 00:00:00.01)
注意,Range分区,如果设定了Max分区,则不能直接增加分区,否则数据会出现重叠。比如
CREATE TABLE "td_max" (
"d" datetime DEFAULT NULL,
"id" int(11) DEFAULT NULL
) ENGINE=EXPRESS DEFAULT CHARSET=utf8 TABLESPACE='sys_tablespace'
PARTITION BY RANGE (d)
(PARTITION p_20230307 VALUES LESS THAN (20230307000000) TABLESPACE = 'sys_tablespace' ENGINE = EXPRESS,
PARTITION p_max VALUES LESS THAN MAXVALUE
可以考虑将MAXVALUE分区删除,如果有数据。可以将MAXVALUE分区数据临时迁移到一个表里,然后删除MAXVALUE分区,建好分区后,再把数据迁移过来。
create table tmp as select * frm td_max partition(p_max);
alter table td_max drop partition p_max;
alter table add partition ....
insert into td_max select * from tmp;
drop table tmp;
删除分区
alter table td_max drop partition p_max;