Paimon也有聚合表了?

<1> Deduplicate--默认

当 Paimon 接收到两条或更多具有相同主键的记录时,它会将它们合并为一条记录以保持主键的唯一性

记录保留策略:

  • 保留最新记录:Paimon 只会保留最新的记录,并丢弃其他具有相同主键的记录。
  • 处理 DELETE 记录:如果最新的记录是一条 DELETE 记录,则所有具有相同主键的记录都将被删除。

配置选项:

  • ignore-delete :用户可以配置 ignore-delete 参数来忽略 DELETE 记录。默认情况下,DELETE 记录会导致所有具有相同主键的记录被删除,但通过设置 ignore-delete=true,可以忽略 DELETE 记录。

示例配置:

sql 复制代码
CREATE TABLE my_table (
    id INT,
    name STRING,
    age INT,
    PRIMARY KEY (id) NOT ENFORCED
)
WITH (
    'merge-engine' = 'deduplicate',
    'ignore-delete' = 'true'
);

注意事项:

  • 在 Flink SQL 的 TableConfig 中,将 table.exec.sink.upsert-materialize 设置为 NONE,以避免启用 upsert-materialize 可能导致的奇怪行为\[1, 4, 17]。
  • 当输入数据无序时,建议使用序列字段(Sequence Field)来纠正乱序\[1, 4, 17]。
  • 如果最新记录是 DELETE 记录,则所有具有相同主键的记录都将被删除,除非配置了 ignore-delete=true 来忽略 DELETE 记录。

<2> aggregation函数

对于paimon而言,实现类似Doris那种聚合模型的功能,只需要三步

  1. 指定主键
  2. 指定merge-engine为aggregation
  3. 指定聚合字段的function
sql 复制代码
CREATE TABLE my_table (
    product_id BIGINT,
    price DOUBLE,
    sales BIGINT,
    PRIMARY KEY (product_id) NOT ENFORCED
) WITH (
    'merge-engine' = 'aggregation',
    'fields.price.aggregate-function' = 'max',
    'fields.sales.aggregate-function' = 'sum'
);
<1, 23.0, 15> 
<1, 30.2, 20>
the final result will be <1, 30.2, 35>.
​
CREATE TABLE my_table (
    product_id BIGINT,
    name varchar,
    price DOUBLE,
    sales BIGINT,
    PRIMARY KEY (product_id) NOT ENFORCED
) WITH (
    'merge-engine' = 'aggregation',
    'fields.price.aggregate-function' = 'max',
    'fields.sales.aggregate-function' = 'sum'
);
<1, 张三, 23.0, 15> 
<1, 李四, 30.2, 20>
最终结果:<1, 李四, 30.2, 35>

《1》常见的聚合函数

max、min、sum、count、lastvalue、last nonnull value、firstvalue、first nonnullvalue、collect

《2》特殊的聚合函数

listagg: 将多个字符串连接成一个字符串,默认用,分隔

bool_and: 评估布尔集中的所有值是否为 true

bool_or: 检查布尔集中是否至少有一个值为 true。

rbm32: 将多个序列化的 32 位 RoaringBitmap 聚合成一个 RoaringBitmap。

rbm64: 将多个序列化的 64 位 Roaring64Bitmap 聚合成一个 Roaring64Bitmap。

nested_update: 将多行收集到一个数组中(所谓的"嵌套表")。用于指定嵌套表的主键。如果没有键,则 row 将被附加到数组中。fields.<field-name>.nested-key=pk0,pk1,... 案例如下:

sql 复制代码
-- orders table
CREATE TABLE orders (
  order_id BIGINT PRIMARY KEY NOT ENFORCED,
  user_name STRING,
  address STRING
);
​
-- sub orders that have the same order_id 
-- belongs to the same order
CREATE TABLE sub_orders (
  order_id BIGINT,
  sub_order_id INT,
  product_name STRING,
  price BIGINT,
  PRIMARY KEY (order_id, sub_order_id) NOT ENFORCED
);
​
-- wide table
CREATE TABLE order_wide (
  order_id BIGINT PRIMARY KEY NOT ENFORCED,
  user_name STRING,
  address STRING,
  sub_orders ARRAY<ROW<sub_order_id BIGINT, product_name STRING, price BIGINT>>
) WITH (
  'merge-engine' = 'aggregation',
  'fields.sub_orders.aggregate-function' = 'nested_update',
  'fields.sub_orders.nested-key' = 'sub_order_id' --这是为了将array中相同nested-key的进行覆盖,不同nested-key的进行nested_update追加
);
​
-- orders
INSERT INTO orders VALUES (1, 'Alice', 'Beijing');
-- sub_orders
INSERT INTO sub_orders VALUES (1, 1, 'iPhone', 5999);
INSERT INTO sub_orders VALUES (1, 2, 'MacBook', 12999);
​
-- widen
INSERT INTO order_wide
SELECT 
  order_id, 
  user_name,
  address, 
  CAST (NULL AS ARRAY<ROW<sub_order_id BIGINT, product_name STRING, price BIGINT>>) 
FROM orders -- 1, 'Alice', 'Beijing', null
​
UNION ALL 
  
SELECT 
  order_id, 
  CAST (NULL AS STRING), 
  CAST (NULL AS STRING), 
  ARRAY[ROW(sub_order_id, product_name, price)] 
FROM sub_orders;-- 1, null, null, [{"sub_order_id":1,"product_name":"iphone","price":5999},
{"sub_order_id":2,"product_name":"MacBook","price":12999}]
​
-- query using UNNEST
SELECT order_id, user_name, address, sub_order_id, product_name, price 
FROM order_wide, UNNEST(sub_orders) AS so(sub_order_id, product_name, price)

补充:select。。。unnest(sub_orders)
作用:
将宽表中的嵌套数组(sub_orders)展开成扁平结构,便于查询。
效果:
类似于 SQL JOIN,但更高效(因为数据已经预聚合)。
最终order_wide数据如下:
{
   "order_id":1,
   "user_name":"Alice",
   "address":"Beijing",
   "sub_orders":[
      {"sub_order_id":1,"product_name":"iPhone","price":5999},
      {"sub_order_id":2,"product_name":"MacBook","price":12999}
   ]
}
查询的结果如下
order_id    user_name   address sub_order_id    product_name    price
1               Alice   Beijing     1               iPhone      5999
1               Alice   Beijing     2               MacBook     12999

**mergemap: **mergemap 函数 merge input maps。它仅支持 MAP 类型。

<3> first row

  1. 功能概述

通过指定 'merge-engine' = 'first-row',用户可以保留同一主键的第一行数据。这与 deduplicate 合并引擎不同,first-row 引擎只会生成插入类型的更改日志。

  1. 使用限制
  • Changelog Producer : first-row 合并引擎必须与 lookup changelog producer 一起使用。
  • Sequence Field : 不能指定 sequence.field。
  • 消息类型 : 不接受 DELETE 和 UPDATE_BEFORE 消息。可以通过配置 first-row.ignore-delete 来忽略这两种记录。
  1. 可见性保证
  • 文件级别为0的文件只有在完成合并后才会可见。默认情况下,合并是同步的,如果开启异步合并,可能会有数据延迟。
  1. 应用场景

first-row 合并引擎在流计算中非常有用,可以替代日志去重功能。

  1. 配置示例

以下是一个使用 first-row 合并引擎的表创建示例:

sql 复制代码
CREATE TABLE test (
    key INT,
    field_a INT,
    field_b INT,
    field_c INT,
    field_d INT,
    PRIMARY KEY (key) NOT ENFORCED
) WITH (
    'merge-engine' = 'first-row',
    'changelog-producer' = 'lookup'
);

注意事项

  • 删除向量 : 合并引擎不能是 first-row,因为 first-row 引擎的读取已经没有合并,不需要删除向量。
  • 性能优化 : 由于 first-row 引擎的状态数据只存储主键信息,可以显著提高状态访问效率,从而提升实时计算任务的性能。
相关推荐
码事漫谈2 小时前
黄仁勋被裁第一天,就收到了橄榄枝
后端
金銀銅鐵3 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
皮皮林5514 小时前
比 Xshell 还好用的 SSH 客户端神器,MobaXterm 太爱了!
后端
我不会起名字3225 小时前
会话缓存失效排查:区分 Redis 失效与节点广播
redis·后端·go·即时通讯·im·故障排查
深入云栈7 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang7 小时前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷7 小时前
iOS 上架 App 流程
后端·ios
code_Bo8 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户8356290780518 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户8356290780518 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python