3.7.4 自动分区¶
1 使用场景¶
自动分区功能主要解决了用户预期基于某列对表进行分区操作,但该列的数据分布比较零散或者难以预测,在建表或调整表结构时难以准确创建所需分区,或者分区数量过多以至于手动创建过于繁琐的问题。
以时间类型分区列为例,在动态分区功能中,我们支持了按特定时间周期自动创建新分区以容纳实时数据。对于实时的用户行为日志等场景该功能基本能够满足需求。但在一些更复杂的场景下,例如处理非实时数据时,分区列与当前系统时间无关,且包含大量离散值。此时为提高效率我们希望依据此列对数据进行分区,但数据实际可能涉及的分区无法预先掌握,或者预期所需分区数量过大。这种情况下动态分区或者手动创建分区无法满足我们的需求,自动分区功能很好地覆盖了此类需求。
假设我们的表 DDL
如下:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
该表内存储了大量业务历史数据,依据交易发生的日期进行分区。可以看到在建表时,我们需要预先手动创建分区。如果分区列的数据范围发生变化,例如上表中增加了 2022
年的数据,则我们需要通过 ALTER-TABLE-PARTITION
对表的分区进行更改。如果这种分区需要变更,或者进行更细粒度的细分,修改起来非常繁琐。此时我们就可以使用 AUTO PARTITION
改写该表 DDL
。
2 语法¶
建表时,使用以下语法填充 CREATE-TABLE
时的 partition_info
部分:
-
AUTO RANGE PARTITION
:SQL 1 2 3
AUTO PARTITION BY RANGE (FUNC_CALL_EXPR) ( )
其中
SQL 1
FUNC_CALL_EXPR ::= date_trunc ( <partition_column>, '<interval>' )
注意:在
2.1.0
版本,FUNC_CALL_EXPR
外围不需要被括号包围。 -
AUTO LIST PARTITION
:SQL 1 2 3
AUTO PARTITION BY LIST(`partition_col`) ( )
2.1 用法示例¶
-
AUTO RANGE PARTITION
SQL 1 2 3 4 5 6 7 8 9 10 11
CREATE TABLE `date_table` ( `TIME_STAMP` datev2 NOT NULL COMMENT '采集日期' ) ENGINE=OLAP DUPLICATE KEY(`TIME_STAMP`) AUTO PARTITION BY RANGE (date_trunc(`TIME_STAMP`, 'month')) ( ) DISTRIBUTED BY HASH(`TIME_STAMP`) BUCKETS 10 PROPERTIES ( "replication_allocation" = "tag.location.default: 1" );
-
AUTO LIST PARTITION
SQL 1 2 3 4 5 6 7 8 9 10 11
CREATE TABLE `str_table` ( `str` varchar not null ) ENGINE=OLAP DUPLICATE KEY(`str`) AUTO PARTITION BY LIST (`str`) ( ) DISTRIBUTED BY HASH(`str`) BUCKETS 10 PROPERTIES ( "replication_allocation" = "tag.location.default: 1" );
2.2 约束¶
-
在
AUTO LIST PARTITION
中,分区名长度不得超过50
。该长度来自于对应数据行上各分区列内容的拼接与转义,因此实际容许长度可能更短。 -
在
AUTO RANGE PARTITION
中,分区函数仅支持date_trunc
,分区列仅支持DATE
或者DATETIME
类型; -
在
AUTO LIST PARTITION
中,不支持函数调用,分区列支持BOOLEAN
,TINYINT
,SMALLINT
,INT
,BIGINT
,LARGEINT
,DATE
,DATETIME
,CHAR
,VARCHAR
数据类型,分区值为枚举值。 -
在
AUTO LIST PARTITION
中,分区列的每个当前不存在对应分区的取值,都会创建一个独立的新PARTITION
。
2.3 NULL 值分区¶
当开启 session variable
allow_partition_column_nullable
后, LIST
和 RANGE
分区都支持 NULL
列作为分区列。当分区列实际遇到 NULL
值的插入时:
-
对于
AUTO LIST PARTITION
,会自动创建对应的NULL
值分区:SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
mysql> create table auto_null_list( -> k0 varchar null -> ) -> auto partition by list (k0) -> ( -> ) -> DISTRIBUTED BY HASH(`k0`) BUCKETS 1 -> properties("replication_num" = "1"); Query OK, 0 rows affected (0.10 sec) mysql> insert into auto_null_list values (null); Query OK, 1 row affected (0.28 sec) mysql> select * from auto_null_list; +------+ | k0 | +------+ | NULL | +------+ 1 row in set (0.20 sec) mysql> select * from auto_null_list partition(pX); +------+ | k0 | +------+ | NULL | +------+ 1 row in set (0.20 sec)
-
对于
AUTO RANGE PARTITION
,不支持NULLABLE
列作为分区列。SQL 1 2 3 4 5 6 7 8 9 10 11 12 13 14
mysql> CREATE TABLE `range_table_nullable` ( -> `k1` INT, -> `k2` DATETIMEV2(3), -> `k3` DATETIMEV2(6) -> ) ENGINE=OLAP -> DUPLICATE KEY(`k1`) -> AUTO PARTITION BY RANGE (date_trunc(`k2`, 'day')) -> ( -> ) -> DISTRIBUTED BY HASH(`k1`) BUCKETS 16 -> PROPERTIES ( -> "replication_allocation" = "tag.location.default: 1" -> ); ERROR 1105 (HY000): errCode = 2, detailMessage = AUTO RANGE PARTITION doesn't support NULL column
3 场景示例¶
在使用场景一节中的示例,在使用 AUTO PARTITION
后,该表 DDL
可以改写为:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
此时新表没有默认分区:
SQL | |
---|---|
1 2 |
|
经过插入数据后再查看,发现该表已经创建了对应的分区:
SQL | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
经过自动分区功能所创建的 PARTITION
,与手动创建的 PARTITION
具有完全一致的功能性质。
4 与动态分区联用¶
为使分区逻辑清晰, Doris
禁止自动分区( Auto Partition
)和动态分区( Dynamic Partition
)同时作用于一张表上,这种用法容易引发误用,应当以单独的自动分区功能代替。
注意:在 Doris 2.1
的某些早期版本中,该功能未被禁止,但不推荐使用。
5 注意事项¶
-
如同普通分区表一样,
AUTO LIST PARTITION
支持多列分区,语法并无区别。 -
在数据的插入或导入过程中如果创建了分区,而整个导入过程没有完成(失败或被取消),被创建的分区不会被自动删除。
-
使用
AUTO PARTITION
的表,只是分区创建方式上由手动转为了自动。表及其所创建分区的原本使用方法都与非AUTO PARTITION
的表或分区相同。 -
为防止意外创建过多分区,我们通过
FE
配置项中的max_auto_partition_num
控制了一个AUTO PARTITION
表最大容纳分区数。如有需要可以调整该值 -
向开启了
AUTO PARTITION
的表导入数据时,Coordinator
发送数据的轮询间隔与普通表有所不同。具体请见BE
配置项中的olap_table_sink_send_interval_auto_partition_factor
。开启前移(enable_memtable_on_sink_node = true
)后该变量不产生影响。 -
在使用
insert-overwrite
插入数据时,如果指定了覆写的partition
,则AUTO PARTITION
表在此过程中表现得如同普通表,不创建新的分区。 -
如果导入创建分区时,该表涉及其他元数据操作(如
Schema Change
、Rebalance
),则导入可能失败。