深入了解所选数据库的核心功能与能力边界,是避免技术选型失误的关键。例如,一个刚刚决定采用Doris的团队,在业务上面临着一个典型挑战:如何高效地将来自多张不同业务表的数据进行“打宽”处理。
他们最初的想法是借助ETL工具,对来自上游MySQL等数据源,通过SQL的Join操作将多表字段合并后,再写入Doris。这种方法在技术上固然可行,但实现复杂度较高。对于追求敏捷的团队,我们建议尝试一种更轻量的方案:利用Doris自2.x版本开始支持的Partial Update(部分列更新)功能。
官方文档的描述固然清晰,但实际应用效果如何?本文将通过实战测试,为你揭示细节。先说结论:功能可用,但在使用上有诸多注意事项。
功能定位对比
在测试Doris之前,我们曾深度测评过Apache Paimon的Partial Update功能,其在“数据打宽”场景下表现不错。通读两者文档后发现,其功能定位存在差异:
- Paimon:将其定位为“主键表下的一种Merge策略”。

- Doris:则将其定位为“主键表模型下的一种更新策略”。

不过,对于使用者而言,定位差异并非关键。重要的是,Paimon的文档指引更为直观,而Doris的Partial Update功能则需要仔细研读文档,才能避开其中的一些“弯弯绕绕”。
启用前置条件
经过实测,要使Doris的Partial Update功能正常工作,必须满足以下三个条件:
- 表类型限制:必须创建主键模型表(Unique Key) 或聚合模型表(Aggregate Key)。
- 开启功能开关:必须通过会话变量开启功能:
SET enable_unique_key_partial_update=true;。经验证,此设置无法写入建表属性中。
- 关闭严格模式:同样需要通过会话变量关闭严格写入模式:
SET enable_insert_strict=false;,否则数据无法插入。
官网提及的其他条件多为默认设置,此处不再赘述。从条件看,Doris的启用方式与Paimon有较大区别。
主键模型表的实践与限制
尽管Doris官方文档大量使用主键模型表举例,但从实测来看,其用于Partial Update场景并不便捷,主要存在以下限制:
1. Sequence Column类型限制
尝试创建一个类似Paimon用法的普通主键模型表,意图让每个字段只有在值大于旧值时才会更新(通过设置sequence column实现):
CREATE TABLE doris_partial_update01 (
id BIGINT,
age INT,
name STRING,
address STRING
)
UNIQUE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 3
PROPERTIES (
"function_column.sequence_col" = "age",
"function_column.sequence_col" = "name",
"function_column.sequence_col" = "address"
);
执行将报错:
ERROR 1105 (HY000): errCode = 2, detailMessage = errCode = 2, detailMessage = Sequence type only support integer types and date types
这表明Doris的sequence column仅支持整型或日期类型。因此,上述表中仅有age字段有资格作为sequence column。
2. Sequence Column更新限制
修改建表语句,仅指定age为sequence column:
PROPERTIES (
"function_column.sequence_col" = "age"
);
写入数据测试:
mysql> insert into doris_partial_update01 (id,age) values(1,11);
Query OK, 1 row affected
mysql> select * from doris_partial_update01;
+------+------+------+---------+
| id | age | name | address |
+------+------+------+---------+
| 1 | 11 | NULL | NULL |
+------+------+------+---------+
mysql> insert into doris_partial_update01 (id,name) values(1,'A');
ERROR 1105 (HY000): Table doris_partial_update01 has sequence column, need to specify the sequence column
可见,一旦建表时指定了sequence column,后续每次数据写入都必须包含该列,否则会执行失败。这与Paimon的灵活处理方式不同。
3. 难以添加聚合列
在之前测试Paimon时,我们喜欢添加一个用于记录每行更新次数的字段,这有助于监控数据质量。但在Doris的主键模型表中,暂时未找到简便的实现方法。
更优解:聚合模型表实践
很多时候,官方推荐并非唯一路径。尝试换用聚合模型表(Aggregate Key),反而能更优雅地实现所有需求,且效果更佳。
创建聚合模型表如下:
CREATE TABLE doris_partial_update02 (
id BIGINT,
age INT MAX,
name varchar(50) REPLACE_IF_NOT_NULL ,
address varchar(100) REPLACE_IF_NOT_NULL ,
update_cnt INT SUM DEFAULT 1
)
AGGREGATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 3
此表设计巧妙实现了全部预期功能:
age 字段:每次更新取最大值(MAX聚合)。
name、address 字段:每次取最新写入且非空的值(REPLACE_IF_NOT_NULL聚合)。
update_cnt 字段:自动累加,用于统计每行执行Partial Update的总次数(SUM聚合,默认值1)。
以下是实战效果演示:
-- 第一次插入,只更新age
mysql> insert into doris_partial_update02 (id,age) values(1,10);
Query OK, 1 row affected
mysql> select * from doris_partial_update02;
+------+------+------+---------+------------+
| id | age | name | address | update_cnt |
+------+------+------+---------+------------+
| 1 | 10 | NULL | NULL | 1 |
+------+------+------+---------+------------+
-- 第二次部分更新,只更新address
mysql> insert into doris_partial_update02 (id,address) values(1,'China');
Query OK, 1 row affected
mysql> select * from doris_partial_update02;
+------+------+------+---------+------------+
| id | age | name | address | update_cnt |
+------+------+------+---------+------------+
| 1 | 10 | NULL | China | 2 |
+------+------+------+---------+------------+
-- 第三次部分更新,更新age和name(age新值更小,未被采纳)
mysql> insert into doris_partial_update02 (id,age,name) values(1,9,'A');
Query OK, 1 row affected
mysql> select * from doris_partial_update02;
+------+------+------+---------+------------+
| id | age | name | address | update_cnt |
+------+------+------+---------+------------+
| 1 | 10 | A | China | 3 |
+------+------+------+---------+------------+
-- 第四次部分更新,更新age和name(age新值更大,被采纳)
mysql> insert into doris_partial_update02 (id,age,name) values(1,15,'A');
Query OK, 1 row affected
mysql> select * from doris_partial_update02;
+------+------+------+---------+------------+
| id | age | name | address | update_cnt |
+------+------+------+---------+------------+
| 1 | 15 | A | China | 4 |
+------+------+------+---------+------------+
整个过程清晰展示了基于聚合模型的Partial Update如何灵活工作,并且自动完成了更新次数的统计。
总结
虽然Doris Partial Update的配置过程略显曲折,但最终通过聚合模型表找到了一个效果良好的解决方案,完全满足了数据打宽场景的需求。这也再次印证,相同的功能在不同的大数据组件中,其实现与最佳实践可能大相径庭。关于该功能在大数据量下的性能表现,我们将在后续文章中继续进行测试。