全部产品
Search
文档中心

数据湖构建:Paimon Append 表

更新时间:Jul 30, 2026

本文介绍 DLF Paimon Append(非主键)表的基本特性与功能。

快速决策

类别

场景

配置建议

分桶方式

海量追加、不关心顺序与点查(如日志、埋点、ODS 明细等)。

无分桶(默认)'bucket' = '-1'

同 key 数据流读顺序需要和写入顺序相同

固定分桶'bucket' = '<num>'

需要按 key 做数据裁剪,或者需要 Spark 的 bucketed join 优化

'bucket-key' = 'c1,c2'

行级更新删除

通过 Spark 对 Append 表轻量化做 DELETE / UPDATE / MERGE INTO

'deletion-vectors.enabled' = 'true'

聚簇优化

经常按某列进行过滤,希望提升查询性能

'clustering.incremental' = 'true''clustering.columns' = 'c1,c2'

说明

如需存储和高效查询多模态数据,详情请参见多模态湖。

基本概念

创建 Paimon 表时未指定主键(primary key),该表即为 Paimon Append 表。以下 SQL 创建一张分区键为 dt 的 Append 表:

CREATE TABLE T (
  user_id BIGINT,
  event_time TIMESTAMP(3),
  event_type STRING,
  properties STRING,
  dt STRING
) PARTITIONED BY (dt);

Append 表具有如下特点:

  • 仅追加写入:接收 insert-only 数据流。若上游为 changelog,需确保无 -U/-D 数据,或设置 ignore-delete = true(默认 false)忽略 -U/-D 数据。

  • 完善的批读批写能力:类似 Hive 分区表,但额外具备 Time travel(版本回滚)、快速 scan planning(基于分区与列统计 + File Index 裁剪)、Schema evolution(加列、删列、改列、改名无副作用)、行级别删除更新(通过删除向量)。

  • 支持流读流写:可像队列一样灵活地流式读写,延迟在分钟级。

与主键表相比,Append 表适合不需要按主键更新的追加型数据,典型如日志、埋点、ODS 明细、binlog 落地、特征/样本表等。

分桶方式

Append 表支持两种分桶模式。

无分桶(默认)

创建 Append 表时不指定 bucket,或指定 'bucket' = '-1',即为无分桶模式。数据写入时不区分分桶,不保证顺序。该模式优势如下:

  • 写入并行度不受分桶数限制,可使用较高并发写入。

  • 无需预估分桶数,也无需随数据量变化手动调整。

适用于海量追加、不关心顺序与点查的场景,如日志、埋点、ODS 明细等。

固定分桶

在表参数中指定 'bucket' = '<num>'(大于 0 的整数),并通过 'bucket-key' 指定分桶键(多个用逗号分隔),即可设定非分区表的分桶数,或分区表单分区的分桶数。

相比无分桶,固定分桶的优势:

  • 同一桶中的数据按写入顺序读出。若需同 key 数据按序读取,可将其设为 bucket-key。

  • 查询条件包含 bucket-key 的等值(=)或 IN 条件时,可利用 bucket 裁剪加速查询。

  • 两张 Append 表 bucket 相同且 bucket-key 用于 Join 等值条件时,Spark 可利用 Bucketed Join 减少资源消耗。

Spark Bucketed Join 示例:

CREATE TABLE t1 (
  user_id BIGINT,
  event_type STRING
) TBLPROPERTIES (
  'bucket' = '16',
  'bucket-key' = 'user_id'
);

CREATE TABLE t2 (
  user_id BIGINT,
  profile STRING
) TBLPROPERTIES (
  'bucket' = '16',
  'bucket-key' = 'user_id'
);

-- Bucketed Join
SELECT *
FROM t1
JOIN t2
ON t1.user_id = t2.user_id;

行级更新删除

Append 表本身仅追加写入。若需通过 Spark 执行 DELETE / UPDATE / MERGE INTO,可设置 'deletion-vectors.enabled' = 'true'。启用后,删除信息记录到删除向量文件中,查询时据此过滤已删行。DLF 后台优化作业会适时合并删除向量和数据,回收存储空间。

聚簇优化(Clustering)

查询经常按某些列过滤时,可启用 Clustering 对数据重排以提升查询性能。DLF 优化作业定期执行聚簇优化,无需手动运行。

示例:

Flink

-- 无分桶 Append 表
CREATE TABLE app_log (
  dt STRING,
  log_time TIMESTAMP,
  user_id BIGINT,
  event_type STRING,
  url STRING
) PARTITIONED BY (dt) WITH (
  'bucket' = '-1',
  'clustering.incremental' = 'true',
  'clustering.columns' = 'user_id,event_type'
);

-- 分桶 Append 表
CREATE TABLE app_log (
  dt STRING,
  log_time TIMESTAMP,
  user_id BIGINT,
  event_type STRING,
  url STRING
) PARTITIONED BY (dt) WITH (
  'bucket' = '64',
  'bucket-key' = 'user_id',
  'bucket-append-ordered' = 'false',
  'clustering.incremental' = 'true',
  'clustering.columns' = 'event_type'
);

Spark

-- 无分桶 Append 表
CREATE TABLE app_log (
  dt STRING,
  log_time TIMESTAMP,
  user_id BIGINT,
  event_type STRING
) PARTITIONED BY (dt) TBLPROPERTIES (
  'bucket' = '-1',
  'clustering.incremental' = 'true',
  'clustering.columns' = 'user_id,event_type'
);

-- 分桶 Append 表
CREATE TABLE app_log (
  dt STRING,
  log_time TIMESTAMP,
  user_id BIGINT,
  event_type STRING
) PARTITIONED BY (dt) TBLPROPERTIES (
  'bucket' = '16',
  'bucket-key' = 'user_id',
  'bucket-append-ordered' = 'false',
  'clustering.incremental' = 'true',
  'clustering.columns' = 'event_type'
);
重要

Clustering 会重新排序文件,而分桶 Append 表原本有序,因此必须设置 'bucket-append-ordered' = 'false' 才能开启。当前分桶 Append 表聚簇还要求不能开启 Deletion Vectors。

配置说明

场景 1:经常按某些列过滤,希望提升查询性能

'clustering.incremental' = 'true'
'clustering.columns' = 'event_time,user_id'

场景 2:分区停止写入后,自动进行全量 clustering

-- 分区超过三天无新写入,视为历史分区
'clustering.history-partition.idle-to-full-sort' = '3d'

存储优化资源消耗

Append 表存储优化作业的资源消耗受多种因素影响,难以精确计算。经验值:普通表(200 列以下)每 25 GB 数据约需 1 CU*H。实际以账单为准。

影响因素:

  • 小文件数量:优化作业中打开一个文件的消耗约等于读取 4 MB 数据的消耗。若写入文件普遍较小(10 MB 以下),合并时读取开销更大。可通过减少 bucket 数(分桶表)、降低写入并发(非分桶表)、增大 checkpoint 间隔等方式避免过小文件。

  • 小表共享优化作业:满足条件的多张小表可共享同一优化作业(至多 64 张),节省资源。小表判定条件:

    • 未设置 data-evolution.enabled = true(默认 false)

    • 未设置 clustering.incremental = true(默认 false)

    • 未设置 deletion-vectors.enabled = true(默认 false)

    • 每小时写入数据量小于 16 GB