3.7.3 动态分区¶
开启动态分区的表,将会按照设定的规则添加、删除分区,从而对表的分区实现生命周期管理( TTL
),减少用户的使用负担。
动态分区只支持在 DATE/DATETIME
列上进行 Range
类型的分区。
动态分区适用于分区列的时间数据随现实世界同步增长的情况。此时可以灵活的按照与现实世界同步的时间维度对数据进行分区。
对于更为灵活,适用场景更多的数据入库分区,请参阅自动分区功能。
Warning
注意:动态分区功能在被 CCR
同步时将会失效。
如果这个表是被 CCR
复制而来的,即 PROPERTIES
中包含 is_being_synced = true
时,在 show create table
中会显示开启状态,但不会实际生效。当 is_being_synced
被设置为 false
时,这些功能将会恢复生效,但 is_being_synced
属性仅供 CCR
外围模块使用,在 CCR
同步的过程中不要手动设置。
1 使用方式¶
动态分区的规则可以在建表时指定,或者在运行时进行修改。当前仅支持对单分区列的分区表设定动态分区规则。
-
建表时指定
SQL 1 2 3 4 5 6 7 8
CREATE TABLE tbl1 (...) PROPERTIES ( "dynamic_partition.prop1" = "value1", "dynamic_partition.prop2" = "value2", ... )
-
运行时修改
SQL 1 2 3 4 5 6
ALTER TABLE tbl1 SET ( "dynamic_partition.prop1" = "value1", "dynamic_partition.prop2" = "value2", ... )
2 规则参数¶
动态分区的规则参数都以 dynamic_partition.
为前缀:
-
dynamic_partition.enable
是否开启动态分区特性。可指定为
TRUE
或FALSE
。如果不填写,默认为TRUE
。如果为FALSE
,则Doris
会忽略该表的动态分区规则。 -
dynamic_partition.time_unit
(必选参数)动态分区调度的单位。可指定为
HOUR
、DAY
、WEEK
、MONTH
、YEAR
。分别表示按小时、按天、按星期、按月、按年进行分区创建或删除。当指定为
HOUR
时,动态创建的分区名后缀格式为yyyyMMddHH
,例如2020032501
。小时为单位的分区列数据类型不能为DATE
。当指定为
DAY
时,动态创建的分区名后缀格式为yyyyMMdd
,例如20200325
。当指定为
WEEK
时,动态创建的分区名后缀格式为yyyy_ww
。即当前日期属于这一年的第几周,例如2020-03-25
创建的分区名后缀为2020_13
,表明目前为2020
年第13
周。当指定为
MONTH
时,动态创建的分区名后缀格式为yyyyMM
,例如202003
。当指定为
YEAR
时,动态创建的分区名后缀格式为yyyy
,例如2020
。 -
dynamic_partition.time_zone
动态分区的时区,如果不填写,则默认为当前机器的系统的时区,例如
Asia/Shanghai
,如果想获取当前支持的时区设置,可以参考https://en.wikipedia.org/wiki/List_of_tz_database_time_zones。 -
dynamic_partition.start
动态分区的起始偏移,为负数。根据
time_unit
属性的不同,以当天(星期或月)为基准,分区范围在此偏移之前的分区将会被删除。如果不填写,则默认为-2147483648
,即不删除历史分区。此偏移之后至当前时间的历史分区如不存在,是否创建取决于dynamic_partition.create_history_partition
。Warning
注意,若用户设置了
history_partition_num(>0)
,创建动态分区的起始分区就会用max(start, -history_partition_num)
,删除历史分区的时候仍然会保留到start
的范围,其中start < 0
。 -
dynamic_partition.end
(必选参数)动态分区的结束偏移,为正数。根据
time_unit
属性的不同,以当天(星期或月)为基准,提前创建对应范围的分区。 -
dynamic_partition.prefix
(必选参数)动态创建的分区名前缀。
-
dynamic_partition.buckets
动态创建的分区所对应的分桶数量。
-
dynamic_partition.replication_num
动态创建的分区所对应的副本数量,如果不填写,则默认为该表创建时指定的副本数量。
-
dynamic_partition.start_day_of_week
当
time_unit
为WEEK
时,该参数用于指定每周的起始点。取值为1
到7
。其中1
表示周一,7
表示周日。默认为1
,即表示每周以周一为起始点。 -
dynamic_partition.start_day_of_month
当
time_unit
为MONTH
时,该参数用于指定每月的起始日期。取值为1
到28
。其中1
表示每月1
号,28
表示每月28
号。默认为1
,即表示每月以1
号为起始点。暂不支持以29
、30
、31
号为起始日,以避免因闰年或闰月带来的歧义。 -
doris
支持SSD
和HDD
层级存储,可参考分层存储 -
dynamic_partition.create_history_partition
默认为
false
。当置为true
时,Doris
会自动创建所有分区,具体创建规则见下文。同时,FE
的参数max_dynamic_partition_num
会限制总分区数量,以避免一次性创建过多分区。当期望创建的分区个数大于max_dynamic_partition_num
值时,操作将被禁止。当不指定
start
属性时,该参数不生效。 -
dynamic_partition.history_partition_num
当
create_history_partition
为true
时,该参数用于指定创建历史分区数量。默认值为-1
,即未设置。该变量与dynamic_partition.start
作用相同,建议同时只设置一个。 -
dynamic_partition.reserved_history_periods
需要保留的历史分区的时间范围。当
dynamic_partition.time_unit
设置为"DAY/WEEK/MONTH/YEAR"
时,需要以[yyyy-MM-dd,yyyy-MM-dd],[...,...]
格式进行设置。当dynamic_partition.time_unit
设置为"HOUR"
时,需要以[yyyy-MM-dd HH:mm:ss,yyyy-MM-dd HH:mm:ss],[...,...]
的格式来进行设置。如果不设置,默认为"NULL"
。举例说明。假设今天是
2021-09-06
,按天分类,动态分区的属性设置为:time_unit="DAY/WEEK/MONTH/YEAR", end=3, start=-3, reserved_history_periods="[2020-06-01,2020-06-20],[2020-10-31,2020-11-15]"
。则系统会自动保留:
SQL 1 2
["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]"
。则系统会自动保留:
SQL 1
["2020-06-01 00:00:00","2020-06-01 03:00:00"]
这两个时间段的分区。其中,
reserved_history_periods
的每一个[...,...]
是一对设置项,两者需要同时被设置,且第一个时间不能大于第二个时间。
3 创建历史分区规则¶
当 create_history_partition
为 true
,即开启创建历史分区功能时, Doris
会根据 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, -histoty_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
的设置,举例如下。
-
history_partition_num=1
,则系统会自动创建以下分区:SQL 1 2 3 4 5
p20210519 p20210520 p20210521 p20210522 p20210523
-
history_partition_num=5
,则系统会自动创建以下分区:SQL 1 2 3 4 5 6 7
p20210517 p20210518 p20210519 p20210520 p20210521 p20210522 p20210523
-
history_partition_num=-1
即不设置历史分区数量,则系统会自动创建以下分区:SQL 1 2 3 4 5 6 7
p20210517 p20210518 p20210519 p20210520 p20210521 p20210522 p20210523
4 示例¶
-
表
tbl1
分区列k1
类型为DATE
,创建一个动态分区规则。按天分区,只保留最近7
天的分区,并且预先创建未来3
天的分区。SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
CREATE TABLE tbl1 ( k1 DATE, ... ) 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.buckets" = "32" );
假设当前日期为
2020-05-29
。则根据以上规则,tbl1
会产生以下分区:SQL 1 2 3 4
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
个星期的分区。SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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.buckets" = "8" );
假设当前日期为
2020-05-29
,是2020
年的第22
周。默认每周起始为星期一。则以上规则,tbl1
会产生以下分区:SQL 1 2 3
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"
,即以每周三为起始日。则分区如下:SQL 1 2 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")
即分区范围为当周的周三到下周的周二。
Warning
注:
2019-12-31
和2020-01-01
在同一周内,如果分区的起始日期为2019-12-31
,则分区名为p2019_53
,如果分区的起始日期为2020-01-01
,则分区名为p2020_01
。 -
表
tbl1
分区列k1
类型为DATE
,创建一个动态分区规则。按月分区,不删除历史分区,并且预先创建未来2
个月的分区。同时设定以每月3
号为起始日。SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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.buckets" = "8", "dynamic_partition.start_day_of_month" = "3" );
假设当前日期为
2020-05-29
。则基于以上规则,tbl1
会产生以下分区:SQL 1 2 3
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
号为起始日,则分区范围为:SQL 1 2 3
p202004: ["2020-04-28", "2020-05-28") p202005: ["2020-05-28", "2020-06-28") p202006: ["2020-06-28", "2020-07-28")
5 原理与控制行为¶
Doris FE
中有固定的 dynamic partition
控制线程,持续以特定时间间隔(即 dynamic_partition_check_interval_seconds
)进行 dynamic partition
表的分区检查,完成需要的分区创建与删除操作。
具体而言,自动分区将会进行如下检查与操作(我们称此时该表分区的起始包含时间为 START
,末尾包含时间为 END
,省略 property
的 dynamic_partition.
前缀):
-
START
时间之前的所有分区,全部被删除。 -
如果
create_history_partition
为false
,创建当前时间到END
之间的所有分区;如果create_history_partition
为true
,除当前时间到END
之间的分区外,还会创建START
到当前时间的分区。若定义了history_partition_num
,则从当前时间向前创建的分区数量不超过history_partition_num
。
需要注意的是:
-
如果分区时间范围与
[START, END]
范围相交,则认为属于当前dynamic partition
时间范围。 -
如果尝试创建的新分区和现有分区冲突,则保留当前分区,不创建该新分区。如果该行为出现在建表时,
DDL
将会报错。
因此,自动分区表在系统自动维护后,呈现的状态是:
-
START
时间之前,除reserved_history_periods
所指定范围以外,不包含任何分区; -
END
时间之后,保留所有手动创建的分区。 -
除手动删除或意外丢失的分区外,表包含特定范围内的全部分区:
-
如果
create_history_partition
为true
:-
若定义了
history_partition_num
,则特定范围为[max(START, 当前时间 - history_partition_num * time_unit), END]
; -
若未定义
history_partition_num
,则特定范围为[START, END]
;
-
-
如果
create_history_partition
为false
,则特定范围为[当前时间, END]
,同时包含[START, 当前时间)
中既存的分区。
整个特定范围按照
time_unit
划分为若干分区范围。对于任意一个范围,如果其与某个当前存在的分区X
相交,则X
被保留,否则该范围将被dynamic partition
所创建的一个分区所完整覆盖。 -
-
除非分区数量即将超过
max_dynamic_partition_num
,创建将会失败。
6 修改动态分区属性¶
通过如下命令可以修改动态分区的属性:
SQL | |
---|---|
1 2 3 4 5 |
|
某些属性的修改可能会产生冲突。假设之前分区粒度为 DAY
,并且已经创建了如下分区:
SQL | |
---|---|
1 2 3 |
|
如果此时将分区粒度改为 MONTH
,则系统会尝试创建范围为 ["2020-05-01", "2020-06-01")
的分区,而该分区的分区范围和已有分区冲突,所以无法创建。而范围为 ["2020-06-01", "2020-07-01")
的分区可以正常创建。因此, 2020-05-22
到 2020-05-30
时间段的分区,需要自行填补。
7 查看动态分区表调度情况¶
通过以下命令可以进一步查看当前数据库下,所有动态分区表的调度情况:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
-
LastUpdateTime
:最后一次修改动态分区属性的时间 -
LastSchedulerTime
:最后一次执行动态分区调度的时间 -
State
:最后一次执行动态分区调度的状态 -
LastCreatePartitionMsg
:最后一次执行动态添加分区调度的错误信息 -
LastDropPartitionMsg
:最后一次执行动态删除分区调度的错误信息
8 高级操作¶
FE
配置项
-
dynamic_partition_enable
是否开启
Doris
的动态分区功能。默认为false
,即关闭。该参数只影响动态分区表的分区操作,不影响普通表。可以通过修改fe.conf
中的参数并重启FE
生效。也可以在运行时执行以下命令生效:SQL 1 2 3 4 5
# MySQL 协议 ADMIN SET FRONTEND CONFIG ("dynamic_partition_enable" = "true") # HTTP 协议 curl --location-trusted -u username:password -XGET http://fe_host:fe_http_port/api/_set_config?dynamic_partition_enable=true
若要全局关闭动态分区,则设置此参数为
false
即可。 -
dynamic_partition_check_interval_seconds
动态分区线程的执行频率,默认为
600
(10
分钟),即每10
分钟进行一次调度。可以通过修改fe.conf
中的参数并重启FE
生效。也可以在运行时执行以下命令修改:SQL 1 2 3 4 5
# MySQL 协议 ADMIN SET FRONTEND CONFIG ("dynamic_partition_check_interval_seconds" = "7200") # HTTP 协议 curl --location-trusted -u username:password -XGET http://fe_host:fe_http_port/api/_set_config?dynamic_partition_check_interval_seconds=432000
动态分区表与手动分区表相互转换
对于一个表来说,动态分区和手动分区可以自由转换,但二者不能同时存在,有且只有一种状态。
通过执行 ALTER TABLE tbl_name SET ("dynamic_partition.enable" = "<true/false>")
即可调整动态分区开关状态。
关闭动态分区功能后, Doris
将不再自动管理分区,需要用户手动通过 ALTER TABLE
的方式创建或删除分区。动态分区开启后,可能立即根据动态分区规则清理多余分区。