本文介绍云数据库 SelectDB 版动态分区相关的概念和示例,帮助您进行分区的动态管理,降低您的使用成本。
概述
在某些场景下,可能会将数据库表按照天进行分区划分。如果需要手动管理分区,可能由于没有创建分区导致数据导入失败,这给数据库管理人员带来了额外的维护成本。通过动态分区功能,可以在建表时设定动态分区规则。云数据库 SelectDB 版根据指定的规则创建或删除分区,也可以在运行时对现有规则进行变更,从而进行分区管理。
目前云数据库SelectDB版动态分区只支持Range分区且实现了动态添加、删除分区的功能。
创建动态分区表
动态分区的规则可以在建表时指定,或者在运行时进行修改。当前仅支持对单分区列的分区表设定动态分区规则。建表时指定动态分区规则的语法如下。
CREATE TABLE tbl1
(...)
PROPERTIES
(
"dynamic_partition.prop1" = "value1",
"dynamic_partition.prop2" = "value2",
...
)
全局配置项
以下与动态分区相关的配置影响整个SelectDB实例环境。
dynamic_partition_enable
。是否开启动态分区功能,默认为true。该参数只影响动态分区表的分区操作,不影响普通表。
可以在运行时执行如下命令生效。
ADMIN SET FRONTEND CONFIG ("dynamic_partition_enable" = "true")
若要全局关闭动态分区,则设置此参数为false即可。
dynamic_partition_check_interval_seconds
。动态分区线程的执行频率,默认为600(10分钟),即每10分钟进行一次调度,自动创建动态分区。
可以在运行时执行如下命令修改。
ADMIN SET FRONTEND CONFIG ("dynamic_partition_check_interval_seconds" = "7200")
表配置项
动态分区的规则参数都以dynamic_partition.
为前缀,动态分区相关的配置的详细说明如下。
参数名称 | 默认值 | 参数说明 |
dynamic_partition.enable |
| 是否开启动态分区特性。可指定为
|
dynamic_partition.time_unit | 无 | 动态分区调度的单位。可指定为
|
dynamic_partition.time_zone |
| 动态分区的时区。 |
dynamic_partition.start |
| 动态分区的起始偏移,为负数。根据 |
dynamic_partition.end | 无 | 动态分区的结束偏移,为正数。根据 |
dynamic_partition.prefix | 无 | 动态创建的分区名前缀。 |
dynamic_partition.create_history_partition |
| 创建历史分区规则。当不指定 |
dynamic_partition.history_partition_num |
| 指定创建历史分区数量。当 |
dynamic_partition.reserved_history_periods |
| 需要保留的历史分区的时间范围。当 |
dynamic_partition.buckets | 无 | 动态创建的分区所对应的分桶数量。 |
dynamic_partition.start_day_of_week |
| 指定每周的起始点。当 |
dynamic_partition.start_day_of_month |
| 指定每月的起始日期。当 |
dynamic_partition.reserved_history_periods相关参数示例如下
例如:按天分类。
设置动态分区的属性为:
time_unit="DAY/WEEK/MONTH", end=3, start=-3, reserved_history_periods="[2020-06-01,2020-06-20],[2020-10-31,2020-11-15]"
。则系统会自动保留:
["2020-06-01","2020-06-20"],["2020-10-31","2020-11-15"]
设置动态分区的属性为:
time_unit="HOUR", end=3, start=-3, reserved_history_periods="[2020-06-01 00:00:00,2020-06-01 03:00:00]"
。则系统会自动保留:
["2020-06-01 00:00:00","2020-06-01 03:00:00"]
这两个时间段的分区。其中,
reserved_history_periods
的每一个[...,...]
是一对设置项,两者需要同时被设置,且第一个时间不能大于第二个时间。
历史分区创建规则
当create_history_partition
为TRUE
,即开启创建历史分区功能时,SelectDB会根据dynamic_partition.start
和dynamic_partition.history_partition_num
来决定创建历史分区的个数。
例如:需要创建的历史分区数量为expect_create_partition_num
,根据不同的设置具体数量如下。
create_history_partition=true
dynamic_partition.history_partition_num
未设置,即-1。则expect_create_partition_num=end-start
;dynamic_partition.history_partition_num
已设置,则expect_create_partition_num=end-Max(start,-history_partition_num)
;
create_history_partition=false
不会创建历史分区,则expect_create_partition_num=end-0
。
当expect_create_partition_num
大于max_dynamic_partition_num
(默认500)时,禁止创建过多分区。
历史分区示例
例如:今天是2021-05-20,按天分区,动态分区的属性设置为:
create_history_partition=true, end=3, start=-3, history_partition_num=1
,则系统会自动创建以下分区。p20210519 p20210520 p20210521 p20210522 p20210523
例如:今天是2021-05-20,按天分区,动态分区的属性设置为:
create_history_partition=true, end=3, start=-3, history_partition_num=5
,则系统会自动创建以下分区。p20210517 p20210518 p20210519 p20210520 p20210521 p20210522 p20210523
例如:今天是2021-05-20,按天分区,动态分区的属性设置为:
create_history_partition=true, end=3, start=-3, history_partition_num=-1
,即不设置历史分区数量,则系统会自动创建以下分区。p20210517 p20210518 p20210519 p20210520 p20210521 p20210522 p20210523
重要动态分区使用过程中,如果因为一些意外情况导致
dynamic_partition.start
和dynamic_partition.end
之间的某些分区丢失,那么当前时间与dynamic_partition.end
之间的丢失分区会被重新创建,dynamic_partition.start
与当前时间之间的丢失分区不会重新创建。
使用示例
表
tbl1
分区列k1类型为DATE,创建一个动态分区规则。按天分区,只保留最近7天的分区,并且预先创建未来3天的分区。CREATE TABLE tbl1 ( k1 DATE, k2 int ) PARTITION BY RANGE(k1) () DISTRIBUTED BY HASH(k1) PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.start" = "-7", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition" = "true", "dynamic_partition.buckets" = "32" );
例如:当前日期为2020-05-29。则根据以上规则,表
tbl1
会产生以下分区:p20200529: ["2020-05-29", "2020-05-30") p20200530: ["2020-05-30", "2020-05-31") p20200531: ["2020-05-31", "2020-06-01") p20200601: ["2020-06-01", "2020-06-02")
在第二天,即2020-05-30,会创建新的分区
p20200602: ["2020-06-02", "2020-06-03")
在2020-06-06时,因为
dynamic_partition.start
设置为7,则将删除7天前的分区,即删除分区p20200529
。表
tbl1
分区列k1类型为DATETIME
,创建一个动态分区规则。按星期分区,只保留最近2个星期的分区,并且预先创建未来2个星期的分区。CREATE TABLE tbl1 ( k1 DATETIME, ... ) PARTITION BY RANGE(k1) () DISTRIBUTED BY HASH(k1) PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "WEEK", "dynamic_partition.start" = "-2", "dynamic_partition.end" = "2", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition" = "true", "dynamic_partition.buckets" = "8" );
例如:当前日期为2020-05-29,是2020年的第22周。默认每周起始为星期一。则基于以上规则,表
tbl1
会产生以下分区:p2020_22: ["2020-05-25 00:00:00", "2020-06-01 00:00:00") p2020_23: ["2020-06-01 00:00:00", "2020-06-08 00:00:00") p2020_24: ["2020-06-08 00:00:00", "2020-06-15 00:00:00")
其中每个分区的起始日期为该周的周一。同时,因为分区列k1的类型为
DATETIME
,则分区值会补全时分秒部分,且皆为0。在2020-06-15,即第25周时,会删除2周前的分区,即删除
p2020_22
。在上面的例子中,例如指定了周起始日为
"dynamic_partition.start_day_of_week" = "3"
,即以每周三为起始日。则分区如下:p2020_22: ["2020-05-27 00:00:00", "2020-06-03 00:00:00") p2020_23: ["2020-06-03 00:00:00", "2020-06-10 00:00:00") p2020_24: ["2020-06-10 00:00:00", "2020-06-17 00:00:00")
即分区范围为当周的周三到下周的周二。
说明2019-12-31 和 2020-01-01 在同一周内,如果分区的起始日期为 2019-12-31,则分区名为
p2019_53
,如果分区的起始日期为 2020-01-01,则分区名为p2020_01
。表
tbl1
分区列k1类型为DATE
,创建一个动态分区规则。按月分区,不删除历史分区,并且预先创建未来2个月的分区。同时设定以每月3号为起始日。CREATE TABLE tbl1 ( k1 DATE, ... ) PARTITION BY RANGE(k1) () DISTRIBUTED BY HASH(k1) PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "MONTH", "dynamic_partition.end" = "2", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition" = "true", "dynamic_partition.history_partition_num" = "6", "dynamic_partition.buckets" = "8", "dynamic_partition.start_day_of_month" = "3" );
例如:当前日期为2020-05-29。则基于以上规则,表
tbl1
会产生以下分区:p202005: ["2020-05-03", "2020-06-03") p202006: ["2020-06-03", "2020-07-03") p202007: ["2020-07-03", "2020-08-03")
因为没有设置
dynamic_partition.start
,则不会删除历史分区。例如:今天为2020-05-20,并设置以每月28号为起始日,则分区范围为:
p202004: ["2020-04-28", "2020-05-28") p202005: ["2020-05-28", "2020-06-28") p202006: ["2020-06-28", "2020-07-28")
修改动态分区属性
通过如下命令,可以在运行时修改动态分区的属性。
ALTER TABLE tbl1 SET( "dynamic_partition.prop1" = "value1", ...);
某些属性的修改可能会产生冲突。假设之前分区粒度为DAY,并且已经创建了如下分区。
p20200519: ["2020-05-19", "2020-05-20")
p20200520: ["2020-05-20", "2020-05-21")
p20200521: ["2020-05-21", "2020-05-22")
如果此时将分区粒度改为MONTH,则系统会尝试创建范围为["2020-05-01", "2020-06-01")
的分区,而该分区的分区范围和已有分区冲突,所以无法创建。而范围为["2020-06-01", "2020-07-01")
的分区可以正常创建。因此,2020-05-22到2020-05-30时间段的分区,需要自行填补。
删除动态分区表的分区
删除动态分区表的分区,要求提前通过如下命令,关闭动态分区属性。
ALTER TABLE tbl1 SET ("dynamic_partition.enable" = "false");
然后在通过如下命令,删除某个指定的分区。
ALTER TABLE tbl1 DROP PARTITION p20200519;
通常动态分区表的分区删除后,需要重新打开动态分区属性,以便后续业务运行过程中,仍由数仓系统自动管理分区。
ALTER TABLE tbl1 SET ("dynamic_partition.enable" = "true");
查看动态分区表调度情况
通过以下命令可以进一步查看当前数据库下,所有动态分区表的调度情况。
mysql> SHOW DYNAMIC PARTITION TABLES;
+-----------+--------+----------+-------------+------+--------+---------+-----------+----------------+---------------------+--------+------------------------+----------------------+-------------------------+
| TableName | Enable | TimeUnit | Start | End | Prefix | Buckets | StartOf | LastUpdateTime | LastSchedulerTime | State | LastCreatePartitionMsg | LastDropPartitionMsg | ReservedHistoryPeriods |
+-----------+--------+----------+-------------+------+--------+---------+-----------+----------------+---------------------+--------+------------------------+----------------------+-------------------------+
| d3 | true | WEEK | -3 | 3 | p | 1 | MONDAY | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | [2021-12-01,2021-12-31] |
| d5 | true | DAY | -7 | 3 | p | 32 | N/A | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | NULL |
| d4 | true | WEEK | -3 | 3 | p | 1 | WEDNESDAY | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | NULL |
| d6 | true | MONTH | -2147483648 | 2 | p | 8 | 3rd | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | NULL |
| d2 | true | DAY | -3 | 3 | p | 32 | N/A | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | NULL |
| d7 | true | MONTH | -2147483648 | 5 | p | 8 | 24th | N/A | 2020-05-25 14:29:24 | NORMAL | N/A | N/A | NULL |
+-----------+--------+----------+-------------+------+--------+---------+-----------+----------------+---------------------+--------+------------------------+----------------------+-------------------------+
7 rows in set (0.02 sec)
LastUpdateTime: 最后一次修改动态分区属性的时间。
LastSchedulerTime: 最后一次执行动态分区调度的时间。
State: 最后一次执行动态分区调度的状态。
LastCreatePartitionMsg: 最后一次执行动态添加分区调度的错误信息。
LastDropPartitionMsg: 最后一次执行动态删除分区调度的错误信息。
高级操作
对于一个表来说,动态分区和手动分区可以自由转换,但二者不能同时存在,只能有一种状态。
手动分区转换为动态分区
如果一个表在创建时未指定动态分区,可以通过ALTER TABLE
在运行时修改动态分区相关属性来转化为动态分区。
开启动态分区功能后,将不再允许手动管理分区,会根据动态分区属性来自动管理分区。
如果已设定dynamic_partition.start
,分区范围在动态分区起始偏移之前的历史分区将会被删除。
动态分区转换为手动分区
通过执行ALTER TABLE tbl_name SET ("dynamic_partition.enable" = "false")
即可关闭动态分区功能,将其转换为手动分区表。
关闭动态分区功能后,将不再自动管理分区,需要手动通过ALTER TABLE
方式创建或删除分区。
常见问题
Q:创建动态分区表时提示“Could not create table with dynamic partition when fe config dynamic_partition_enable is false”。
A:由于动态分区的全局开关
dynamic_partition_enable
为false,导致无法创建动态分区表。执行命令ADMIN SET FRONTEND CONFIG ("dynamic_partition_enable" = "true")
将动态分区开关打开即可。Q:关于动态分区的副本设置
A:动态分区是由系统内部的调度逻辑自动创建的。在自动创建分区时,所使用的分区属性(包括分区的副本数等),都是单独使用
dynamic_partition
前缀的属性,而不是使用表的默认属性。示例如下。CREATE TABLE tbl1 ( `k1` int, `k2` date ) PARTITION BY RANGE(k2)() DISTRIBUTED BY HASH(k1) BUCKETS 3 PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.start" = "-3", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition" = "true", "dynamic_partition.buckets" = "32" );
上述示例中,没有创建任何初始分区(PARTITION BY子句中的分区定义为空),并且设置了
DISTRIBUTED BY HASH(k1) BUCKETS 3
和"dynamic_partition.buckets" = "32"
。前一个参数将成为表的默认参数,而后一个参数成为动态分区专用参数。当系统自动创建分区时,会使用分桶数32(即动态分区专用参数),而不是分桶数3。当通过
ALTER TABLE tbl1 ADD PARTITION
语句手动添加分区时,则会使用分桶数3(即表的默认参数)。即动态分区使用一套独立的参数设置,只有当没有设置动态分区专用参数时,才会使用表的默认参数。CREATE TABLE tbl3 ( `k1` int, `k2` date ) PARTITION BY RANGE(k2)( PARTITION p1 VALUES LESS THAN ("2019-10-10") ) DISTRIBUTED BY HASH(k1) BUCKETS 3 PROPERTIES ( "dynamic_partition.enable" = "true", "dynamic_partition.time_unit" = "DAY", "dynamic_partition.start" = "-3", "dynamic_partition.end" = "3", "dynamic_partition.prefix" = "p", "dynamic_partition.create_history_partition" = "true", "dynamic_partition.buckets" = "32" );
这个示例中,有一个手动创建的分区p1。这个分区会使用表的默认设置,即分桶数3。而后续系统自动创建的动态分区,依然会使用动态分区专用参数,即分桶数32。