Paimon主键表的合并机制
数据合并机制
在 Paimon 主键表中,若多条数据具有相同主键,系统会根据 WITH
参数中的 merge-engine
配置进行合并。以下是四种合并机制的详细说明和典型用例:
1. deduplicate(默认值)
- 逻辑:仅保留相同主键的最新一条数据,其余丢弃。若最新数据为
DELETE
消息,则删除该主键所有记录。 - 特点:适用于精确去重场景,保证最终状态由最新操作决定。
- 示例:
CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,v1 DOUBLE,v2 STRING ) WITH ('merge-engine' = 'deduplicate'); -- 可省略(默认值)
- 写入序列:
+I(1, 1.0, 'A')
→+U(1, 2.0, 'B')
→-D(1, 2.0, 'B')
- 最终结果:
k=1
的数据被删除。
- 写入序列:
2. first-row
- 逻辑:保留相同主键的第一条数据,后续数据忽略。
- 特点:仅产生
INSERT
类型变更,吞吐率高,适用于首次出现即固定的场景(如初始化配置)。 - 示例:
CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,v1 DOUBLE,v2 STRING ) WITH ('merge-engine' = 'first-row');
- 写入序列:
+I(1, 2.0, 'apple')
→+I(1, 4.0, 'banana')
→+I(1, 8.0, 'cherry')
- 查询结果:
(1, 2.0, 'apple')
(仅保留第一条)。
- 写入序列:
3. aggregation
- 逻辑:对相同主键的值列进行聚合(如
SUM
、MAX
),需显式指定聚合函数。 - 特点:适用于累加型指标(如销售额统计),支持聚合函数扩展。
- 示例:
CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,sales BIGINT,last_ts TIMESTAMP ) WITH ('merge-engine' = 'aggregation','fields.sales.aggregate-function' = 'sum','fields.last_ts.aggregate-function' = 'max' );
- 写入序列:
+I(1, 100, '2023-01-01 10:00:00')
+U(1, 50, '2023-01-01 11:00:00')
- 查询结果:
(1, 150, '2023-01-01 11:00:00')
(sales
求和,last_ts
取最新)。
- 写入序列:
4. partial-update
逻辑:逐步更新非
NULL
列,最终形成完整记录。支持字段分组和聚合。特点:适用于宽表更新或部分列延迟到达的场景。
基础示例:
CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,v1 DOUBLE,v2 BIGINT,v3 STRING ) WITH ('merge-engine' = 'partial-update');
数据行为:
- 写入序列:
+I(1, 23.0, 10, NULL)
+I(1, NULL, NULL, 'book')
+I(1, 25.2, NULL, NULL)
- 最终结果:
(1, 25.2, 10, 'book')
(NULL
值不覆盖旧数据)。
- 写入序列:
高级控制
a) 字段分组(Sequence Group)
指定字段按特定序列号组更新:CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,a STRING, b STRING, g_1 INT,c STRING, d STRING, g_2 INT ) WITH ('merge-engine' = 'partial-update','fields.g_1.sequence-group' = 'a,b', -- a,b 字段由 g_1 决定更新顺序'fields.g_2.sequence-group' = 'c,d' -- c,d 字段由 g_2 决定更新顺序 );
b) 聚合更新
对组内字段应用聚合函数:CREATE TABLE T (k INT PRIMARY KEY NOT ENFORCED,a STRING, b INT, g_1 INT,c STRING, d INT, g_2 INT ) WITH ('merge-engine' = 'partial-update','fields.g_1.sequence-group' = 'a,b','fields.b.aggregate-function' = 'max', -- b 字段取最大值'fields.g_2.sequence-group' = 'c,d','fields.d.aggregate-function' = 'sum' -- d 字段求和 );
乱序数据处理
问题:默认按写入顺序合并,数据乱序会导致结果不准确。
解决方案:
通过sequence.field
指定排序列(支持TINYINT
/BIGINT
/TIMESTAMP
等),主键相同的数据按该列值升序合并。关键配置:
CREATE TABLE T (...) WITH ('sequence.field' = 'op_ts', -- 指定时间戳列为顺序依据'sequence.auto-padding' = 'row-kind-flag' -- 处理 Update 消息的顺序 );
说明:
- 若使用 CDC 数据(如 MySQL 的
op_ts
),需启用sequence.auto-padding
保证UPDATE_BEFORE
先于UPDATE_AFTER
处理。 - 未配置时,乱序数据可能导致最终状态错误(如旧值覆盖新值)。
- 若使用 CDC 数据(如 MySQL 的
合并机制对比表
合并机制 | 适用场景 | 更新行为 | 特殊能力 |
---|---|---|---|
deduplicate | 仅需最新状态(如维度表) | 保留最后一条 | 支持删除消息 |
first-row | 首次写入即固定(如配置表) | 保留第一条 | 仅产生 INSERT |
aggregation | 指标累加(如销售额统计) | 按规则聚合字段 | 支持 SUM/MAX/MIN 等 |
partial-update | 宽表部分列更新(如用户画像) | 非 NULL 列覆盖 | 字段分组与聚合控制 |
最佳实践建议
- 选择合并机制:
- 优先
deduplicate
(默认),除非有聚合或分批次更新需求。 - 使用
partial-update
时,务必通过sequence-group
控制字段依赖关系。
- 优先
- 乱序处理:
- 在 CDC 场景中必须配置
sequence.field
和sequence.auto-padding
。 - 序列字段需单调递增(如操作时间戳、版本号)。
- 在 CDC 场景中必须配置
- 性能考量:
first-row
写入性能最高(无状态合并),aggregation
和partial-update
需维护中间状态。
通过合理配置合并机制,Paimon 可灵活支持从实时分析到增量数仓的多种场景,同时保证数据一致性和处理效率。