MatrixOne DDL 语句分区支持的说明
1. MatrixOne 支持的分区类型
目前 MatrixOne 的 DDL 语句支持的 6 种分区类型,与 MySQL 官网基本一致,具体如下:
- KEY partitioning
- HASH partitioning
- RANGE partitioning
- RANGE COLUMNS partitioning
- LIST partitioning
- LIST COLUMNS partitioning
2. 关于分区键的说明
Partition Keys, Primary Keys 和 Unique Keys 的关系
分区键(Partition Keys)、主键(Primary Keys)和唯一键(Unique Keys)的关系规则可以概括为:
分区表的分区表达式中使用的所有列必须是该表可能具有的每个唯一键的一部分。
Note
唯一键包括 PrimaryKey 和 Unique KEY。
也就是说,表上的每个唯一键必须使用表的分区表达式中的每一列。唯一键也包括表的主键,因为根据定义,表的主键也是唯一键。
示例说明
例如,以下每个表创建语句都无效:
> CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col2)
)
PARTITION BY HASH(col3)
PARTITIONS 4;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
> CREATE TABLE t2 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1),
UNIQUE KEY (col3)
)
PARTITION BY HASH(col1 + col3)
PARTITIONS 4;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
关于 KEY 分区键为 NULL
KEY 只接受零个或多个列名的列表。在表有主键的情况下,用作分区键的任何列必须包含表主键的一部分或全部。
如果没有指定列名作为分区键,则使用表的主键(如果有)。例如,以下
CREATE TABLE
语句在 MySQL 中有效。如果没有主键,但有 UNIQUE KEY,那么 UNIQUE KEY 用于分区键。
例如,以下建表语句中,KEY 分区分区键为 NULL,没有定义主键,但是含有唯一键,构建分区表达式时则使用唯一键作为分区键:
CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY (col1, col2)
)
PARTITION BY KEY()
PARTITIONS 4;
Note
其他分区规则与 MySQL 基本保持一致。
3. 关于 MatrixOne 分区表达式的说明
在 DDL 语句构建分区表时,会针对每一种分区定义生成一个分区表达式,该分区表达式可用于计算数据的所属的分区。
在计划构建阶段对 DDL 语句中的分区信息数据结构为 plan.PartitionInfo:
type PartitionInfo struct {
Type PartitionType
Expr *Expr
PartitionExpression *Expr
Columns []*Expr
PartitionColumns []string
PartitionNum uint64
Partitions []*PartitionItem
Algorithm int64
IsSubPartition bool
PartitionMsg string
}
其中 PartitionExpression
即为分区表达式。分区表达式为 MatrixOne 把分区子句转换为一个表达式进行处理的方式,对每一种分区表达式的构建方式如下:
KEY Partitioning
KEY 分区会根据分区键和分区数量,构建一个分区表达式,分区表达式的计算结果为一个大于等于 0 的整数,代表分区序号,从零开始依次递增。
SQL 示例如下:
CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
PRIMARY KEY (col1, col2)
)
PARTITION BY KEY(col1)
PARTITIONS 4;
HASH Partitioning
与 KEY 分区类似,HASH 分区会根据分区函数和分区数量,构建一个分区表达式,分区表达式的计算结果为一个大于等于 0 的整数,代表分区序号,从零开始依次递增。
SQL 示例如下:
CREATE TABLE t1 (
col1 INT,
col2 CHAR(5),
col3 DATE
)
PARTITION BY LINEAR HASH( YEAR(col3))
PARTITIONS 6;
RANGE Partitioning
RANGE 分区是基于列值的范围将表的数据划分到不同的分区中的一种方法。这种分区类型非常适合于那些可以根据特定列的值范围进行分段的数据。
SQL 示例如下:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
RANGE COLUMNS partitioning
RANGE COLUMNS 分区允许使用一个或多个列的组合作为分区键,每个分区定义了一个值范围,对应于分区键列的组合值,当插入数据时,根据这些列的值确定行所属的分区。
SQL 示例如下:
CREATE TABLE rc (
a INT NOT NULL,
b INT NOT NULL
)
PARTITION BY RANGE COLUMNS(a,b) (
PARTITION p0 VALUES LESS THAN (10,5) COMMENT = 'Data for LESS THAN (10,5)',
PARTITION p1 VALUES LESS THAN (20,10) COMMENT = 'Data for LESS THAN (20,10)',
PARTITION p2 VALUES LESS THAN (50,MAXVALUE) COMMENT = 'Data for LESS THAN (50,MAXVALUE)',
PARTITION p3 VALUES LESS THAN (65,MAXVALUE) COMMENT = 'Data for LESS THAN (65,MAXVALUE)',
PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE) COMMENT = 'Data for LESS THAN (MAXVALUE,MAXVALUE)'
);
LIST Partitioning
LIST 分区是基于单个列的离散值来划分数据,每个分区包含了列值的一个特定列表,当插入数据时,行根据该列的值被分配到相应的分区。
SQL 示例如下:
CREATE TABLE client_firms (
id INT,
name VARCHAR(35)
)
PARTITION BY LIST (id) (
PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
);
LIST COLUMNS partitioning
LIST COLUMNS 分区类似于 LIST 分区,但允许使用一个或多个列的组合作为分区键,分区是基于列值组合的特定列表,插入行时,根据这些列的组合值来确定其分区。
SQL 示例如下:
CREATE TABLE lc (
a INT NULL,
b INT NULL
)
PARTITION BY LIST COLUMNS(a,b) (
PARTITION p0 VALUES IN( (0,0), (NULL,NULL) ),
PARTITION p1 VALUES IN( (0,1), (0,2) ),
PARTITION p2 VALUES IN( (1,0), (2,0) )
);