手动分区
更新时间:2025-05-29
分区列
- 分区列可以指定一列或多列,分区列必须为 KEY 列。
- 不论分区列是什么类型,在写分区值时,都需要加双引号。
- 分区数量理论上没有上限。但默认限制每张表 4096 个分区,如果想突破这个限制,可以修改 FE 配置
max_multi_partition_num
和max_dynamic_partition_num
。 - 当不使用分区建表时,系统会自动生成一个和表名同名的,全值范围的分区。该分区对用户不可见,并且不可删改。
- 创建分区时不可添加范围重叠的分区。
Range 分区
分区列通常为时间列,以方便的管理新旧数据。Range 分区支持的列类型 DATE, DATETIME, TINYINT, SMALLINT, INT, BIGINT, LARGEINT。
分区信息,支持四种写法:
- FIXED RANGE:定义分区的左闭右开区间。
SQL
1PARTITION BY RANGE(col1[, col2, ...])
2(
3 PARTITION partition_name1 VALUES [("k1-lower1", "k2-lower1", "k3-lower1",...), ("k1-upper1", "k2-upper1", "k3-upper1", ...)),
4 PARTITION partition_name2 VALUES [("k1-lower1-2", "k2-lower1-2", ...), ("k1-upper1-2", MAXVALUE, ))
5)
示例如下:
SQL
1PARTITION BY RANGE(`date`)
2(
3 PARTITION `p201701` VALUES [("2017-01-01"), ("2017-02-01")),
4 PARTITION `p201702` VALUES [("2017-02-01"), ("2017-03-01")),
5 PARTITION `p201703` VALUES [("2017-03-01"), ("2017-04-01"))
6)
- LESS THAN:仅定义分区上界。下界由上一个分区的上界决定。
SQL
1PARTITION BY RANGE(col1[, col2, ...])
2(
3 PARTITION partition_name1 VALUES LESS THAN MAXVALUE | ("value1", "value2", ...),
4 PARTITION partition_name2 VALUES LESS THAN MAXVALUE | ("value1", "value2", ...)
5)
示例如下:
SQL
1PARTITION BY RANGE(`date`)
2(
3 PARTITION `p201701` VALUES LESS THAN ("2017-02-01"),
4 PARTITION `p201702` VALUES LESS THAN ("2017-03-01"),
5 PARTITION `p201703` VALUES LESS THAN ("2017-04-01"),
6 PARTITION `p2018` VALUES [("2018-01-01"), ("2019-01-01")),
7 PARTITION `other` VALUES LESS THAN (MAXVALUE)
8)
- BATCH RANGE:批量创建数字类型和时间类型的 RANGE 分区,定义分区的左闭右开区间,设定步长。
SQL
1PARTITION BY RANGE(int_col)
2(
3 FROM (start_num) TO (end_num) INTERVAL interval_value
4)
5
6PARTITION BY RANGE(date_col)
7(
8 FROM ("start_date") TO ("end_date") INTERVAL num YEAR | num MONTH | num WEEK | num DAY | 1 HOUR
9)
示例如下:
SQL
1PARTITION BY RANGE(age)
2(
3 FROM (1) TO (100) INTERVAL 10
4)
5
6PARTITION BY RANGE(`date`)
7(
8 FROM ("2000-11-14") TO ("2021-11-14") INTERVAL 2 YEAR
9)
4.MULTI RANGE:批量创建 RANGE 分区,定义分区的左闭右开区间。示例如下:
SQL
1PARTITION BY RANGE(col)
2(
3 FROM ("2000-11-14") TO ("2021-11-14") INTERVAL 1 YEAR,
4 FROM ("2021-11-14") TO ("2022-11-14") INTERVAL 1 MONTH,
5 FROM ("2022-11-14") TO ("2023-01-03") INTERVAL 1 WEEK,
6 FROM ("2023-01-03") TO ("2023-01-14") INTERVAL 1 DAY,
7 PARTITION p_20230114 VALUES [('2023-01-14'), ('2023-01-15'))
8)
List 分区
分区列支持 BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR, VARCHAR
数据类型,分区值为枚举值。只有当数据为目标分区枚举值其中之一时,才可以命中分区。
Partition 支持通过 VALUES IN (...)
来指定每个分区包含的枚举值。
举例如下:
SQL
1PARTITION BY LIST(city)
2(
3 PARTITION `p_cn` VALUES IN ("Beijing", "Shanghai", "Hong Kong"),
4 PARTITION `p_usa` VALUES IN ("New York", "San Francisco"),
5 PARTITION `p_jp` VALUES IN ("Tokyo")
6)
List 分区也支持多列分区,示例如下:
SQL
1PARTITION BY LIST(id, city)
2(
3 PARTITION p1_city VALUES IN (("1", "Beijing"), ("1", "Shanghai")),
4 PARTITION p2_city VALUES IN (("2", "Beijing"), ("2", "Shanghai")),
5 PARTITION p3_city VALUES IN (("3", "Beijing"), ("3", "Shanghai"))
6)
NULL 分区
PARTITION 列默认必须为 NOT NULL 列,如果需要使用 NULL 列,应设置 session variable allow_partition_column_nullable = true
。对于 LIST PARTITION,我们支持真正的 NULL 分区。对于 RANGE PARTITION,NULL 值会被划归最小的 LESS THAN 分区。分列如下:
- LIST 分区
SQL
1mysql> create table null_list(
2 -> k0 varchar null
3 -> )
4 -> partition by list (k0)
5 -> (
6 -> PARTITION pX values in ((NULL))
7 -> )
8 -> DISTRIBUTED BY HASH(`k0`) BUCKETS 1
9 -> properties("replication_num" = "1");
10Query OK, 0 rows affected (0.11 sec)
11
12mysql> insert into null_list values (null);
13Query OK, 1 row affected (0.19 sec)
14
15mysql> select * from null_list;
16+------+
17| k0 |
18+------+
19| NULL |
20+------+
211 row in set (0.18 sec)
- RANGE 分区 —— 归属最小的 LESS THAN 分区
SQL
1mysql> create table null_range(
2 -> k0 int null
3 -> )
4 -> partition by range (k0)
5 -> (
6 -> PARTITION p10 values less than (10),
7 -> PARTITION p100 values less than (100),
8 -> PARTITION pMAX values less than (maxvalue)
9 -> )
10 -> DISTRIBUTED BY HASH(`k0`) BUCKETS 1
11 -> properties("replication_num" = "1");
12Query OK, 0 rows affected (0.12 sec)
13
14mysql> insert into null_range values (null);
15Query OK, 1 row affected (0.19 sec)
16
17mysql> select * from null_range partition(p10);
18+------+
19| k0 |
20+------+
21| NULL |
22+------+
231 row in set (0.18 sec)
- RANGE 分区 —— 没有 LESS THAN 分区时,无法插入
SQL
1mysql> create table null_range2(
2 -> k0 int null
3 -> )
4 -> partition by range (k0)
5 -> (
6 -> PARTITION p200 values [("100"), ("200"))
7 -> )
8 -> DISTRIBUTED BY HASH(`k0`) BUCKETS 1
9 -> properties("replication_num" = "1");
10Query OK, 0 rows affected (0.13 sec)
11
12mysql> insert into null_range2 values (null);
13ERROR 5025 (HY000): Insert has filtered data in strict mode, tracking_url=......