Paimon底层存储数据结构和架构原理以及tag功能和paimon入门实例

Apache Paimon

1. Paimon 概述

1.1 什么是 Apache Paimon?

Apache Paimon 是一个开源的流式数据湖存储系统,专门为实时数据处理而设计。它结合了数据湖的灵活性和数据仓库的性能,为现代大数据应用提供了一个统一的存储解决方案。

Apache Paimon 的架构(来自官网):

如上图所示架构:

读/写: Paimon 支持多种数据读/写方式和 OLAP 查询。

  • 对于读取操作,它支持数据消费。
    • 从历史快照(批量模式)
    • 从最新的偏移量(在流媒体模式下)开始,或者
    • 以混合方式读取增量快照。
  • 对于写入操作,它支持
    • 从数据库变更日志(CDC)进行流式同步
    • 从离线数据批量插入/覆盖数据。

**生态系统:**除了 Apache Flink 之外,Paimon 还支持被其他计算引擎读取,如 Apache Hive、Apache Spark 和 Trino。

内部的:

  • 在底层,Paimon 将列式文件存储在文件系统/对象存储中。
  • 文件的元数据保存在清单文件中,提供大规模存储和数据跳过功能。
  • 对于主键表,使用 LSM 树结构来支持大量数据更新和高性能查询。
1.1.1 Paimon 的核心价值

对于初学者来说,Paimon 解决了以下关键问题:

  1. 实时数据处理:传统数据湖(如Hive)主要面向批处理,而Paimon支持实时数据流处理
  2. 简化查询:无需编写复杂的SQL窗口函数即可查询最新数据
  3. 版本控制:内置类似Git的版本管理功能,支持数据回滚和时间旅行
  4. 统一存储:同一份数据同时支持流处理和批处理

统一存储 (https://paimon.apache.org/docs/1.0/concepts/overview/#unified-storage)

对于像 Apache Flink 这样的流式引擎,通常有三种类型的连接器:

  • 消息队列(例如 Apache Kafka)在本管道的源阶段和中间阶段均有使用,以保证延迟保持在几秒以内。
  • OLAP 系统(例如 ClickHouse)以流式方式接收处理后的数据,并响应用户的临时查询。
  • 批量存储,例如 Apache Hive,支持传统批量处理的各种操作,包括INSERT OVERWRITE

Paimon 提供表抽象功能。它的使用方式与传统数据库并无二致:

  • batch执行模式下,它就像一个 Hive 表,支持各种批量 SQL 操作。查询该表即可查看最新快照。
  • streaming执行模式下,它就像一个消息队列。查询模式下,它就像从消息队列中查询流式变更日志,其中历史数据永不过期。
1.1.2 Paimon 与传统数据湖的对比
特性传统数据湖(Hive)Apache Paimon
数据处理模式批处理为主流批一体
实时性延迟较高(小时/天级)低延迟(秒/分钟级)
查询复杂度需要复杂SQL窗口函数直接查询最新数据
版本管理需要外部工具内置Tag和快照机制
存储效率中等高(LSM树优化)

1.2 为什么选择 Paimon?

1.2.1 适用场景

Paimon 特别适合以下应用场景:

  • 实时报表系统:需要分钟级甚至秒级更新的业务报表
  • 实时监控平台:业务指标的实时计算和展示
  • 推荐系统:基于最新用户行为的实时推荐
  • 数据质量监控:实时检测数据质量问题
  • 数据审计追踪:完整的数据变更历史记录
1.2.2 技术优势
  1. 高性能写入:基于LSM树结构,支持高吞吐数据摄入
  2. 高效查询:快照机制直接定位最新数据,避免全表扫描
  3. 灵活扩展:支持水平扩展,适应大数据量场景
  4. 生态兼容:与Flink、Spark等大数据框架深度集成

2. Paimon与传统数据仓库hive的区别

2.1 基础概念

2.1.1 数据湖 vs 数据仓库

数据湖:存储原始数据的存储库,支持各种格式的数据,适合探索性分析
数据仓库:结构化数据的存储系统,适合报表和BI分析
Paimon:结合了两者的优势,既支持灵活的数据格式,又提供高性能的查询能力

2.1.2 流处理 vs 批处理

批处理:处理一批静态数据,如夜间ETL作业
流处理:实时处理连续的数据流,如实时监控
Paimon:支持两种处理模式,实现流批一体

3. Paimon 存储文件结构

3.1 整体文件布局

Apache Paimon 采用流式数据湖存储技术,基于 LSM(Log-Structured Merge-tree)树结构来存储数据,支持高吞吐、低延迟的数据摄入和实时查询。

在这里插入图片描述

Paimon 表的存储目录结构如下:

以前paimon版本(<0.7)
表根目录/
├── snapshot/           # 快照目录
│   ├── snapshot-1      # 快照文件
│   ├── snapshot-2
│   └── ...
├── manifest/           # 清单文件目录
│   ├── manifest-list-1 # 清单列表文件
│   └── ...
├── data/               # 数据文件目录
│   ├── bucket-0/       # 桶0的数据文件
│   ├── bucket-1/       # 桶1的数据文件
│   └── ...
├── metadata/           # 元数据目录
│   ├── schema/         # 表结构定义
│   ├── tags/           # 标签目录
│   └── ...
└── changelog/          # 变更日志目录(可选)


现在版本paimon1.0.1
tbl/
├── bucket-*/        ← 数据文件
├── manifest/        ← 元数据:文件清单
├── schema/          ← 元数据:表结构版本
├── snapshot/        ← 元数据:快照指针
├── index/           ← 可选索引文件
└── tag/             ← 可选永保别名
Manifest文件(数据文件的清单):

Manifest文件是Paimon用来存储元数据信息的文件,记录了数据文件的路径、分区信息、增量变更(添加或删除)、行数等。它是Paimon元数据管理的核心组件。

清单文件记录了数据文件的元数据信息,包括:

  • 数据文件路径
  • 数据统计信息(最小值、最大值等)
  • 文件大小和记录数
  • 数据文件的状态(新增、删除、修改)

在这里插入图片描述

Manifest-list文件(Manifest 的清单):

Manifest-list是一组manifest文件名的列表,用于组织和管理多个manifest文件。它充当了快照与具体manifest文件之间的桥梁。

在这里插入图片描述

Paimon中的Manifest-list分为三种类型:

  1. baseManifestList(基础清单列表)
    • 记录来自之前快照的所有变更
    • 包含历史累积的manifest文件引用
  2. deltaManifestList(增量清单列表)
    • 记录当前快照中发生的新变更
    • 用于更快的过期和流式读取
  3. changelogManifestList(变更日志清单列表)
    • 记录快照中产生的变更日志
    • 为null表示没有变更日志或paimon版本≤0.2
特性Manifest 文件Manifest-list 文件
作用记录一个 bucket 的数据文件变更记录一次快照涉及的所有 Manifest 文件
内容数据文件路径、统计信息、状态Manifest 文件路径、分区、bucket、统计信息
粒度细粒度(bucket 级别)粗粒度(快照级别)
生成频率每次写入 bucket 有变更时每次提交(commit)时
是否被索引被 Manifest-list 索引被快照(snapshot)索引
索引(Index)文件的 Manifest

Paimon 0.8+ 支持次级索引(如 bloom-filter、hash-index、vector-index 等)。
写入数据时,同步或异步生成对应的 index file(通常以 .index 结尾)。
为了快照隔离、增量清理、快速读取,这些索引文件同样需要走 Manifest 机制 → 于是就有了 indexManifest

项目普通 ManifestindexManifest
记录对象数据文件(.parquet)索引文件(.index)
文件前缀manifest-{uuid}-Nindex-manifest-{uuid}-N
内容字段file_path, rowCount, min/max 值…index_type, file_path, size, bloom_bits…
由谁生成Writer(commit)IndexWriter(commit 或 async)
由谁读取Scan / Compact / AuditIndexLookup / Compaction / Clean

在这里插入图片描述

Schema文件:

Schema文件是定义表结构信息的元数据文件,存储表的字段定义、分区键、主键等信息。

在这里插入图片描述

快照文件(Snapshot)

所有快照文件都存储在 snapshot 目录中。快照文件是一个 JSON 文件,包含以下信息

在这里插入图片描述

字段含义
version3快照文件格式版本号(内部协议)
id1快照序号(=1,说明这是表的第 1 次提交)
schemaId9本次使用“编目规则 9 号”→ 去 schema/schema-9.json 看字段定义
baseManifestListmanifest-list-9dbcbe1e…‑0全量文件清单(首次提交时它就是全部)
deltaManifestListmanifest-list-9dbcbe1e…‑1增量文件清单(本次追加的新文件)
changelogManifestListnull没有产生行级变更日志(非流式更新)
commitUserbf11595c…谁提交的(Flink Job 或 Spark Application 的 UUID)
commitIdentifier9223372036854775807Long.MAX_VALUE → 批模式一次性提交
commitKindAPPEND本次只是追加,不是 COMPACT 或 OVERWRITE
timeMillis1763462586227提交瞬间的时间戳(毫秒)
totalRecordCount1整张表现在共 1 条记录
deltaRecordCount1本次追加了 1 条记录
watermark-9223372036854775808Long.MIN_VALUE → 无事件时间概念(批)

snapshot-1 ──schemaId─→ schema/schema-9.json

├─baseManifestList─→ manifest/manifest-list-9dbcbe1e…-0 (全量)
└─deltaManifestList─→ manifest/manifest-list-9dbcbe1e…-1 (增量)


里面列出真正数据文件
bucket-0/data-xxxxx.parquet

tag文件:

在这里插入图片描述

字段含义
version3文件格式协议号(内部协议)
id12被“裱”起来的快照序号
schemaId9用 9 号规则(schema/schema-9.json)解读数据
baseManifestList…-0全量文件清单(首次提交时的全部)
deltaManifestList…-1增量文件清单(本次追加部分)
changelogManifestList…-2有行级变更日志(流式更新产生)
indexManifestindex-manifest-…-9索引文件也有独立 manifest(建了 bloom/hash 等)
commitUser24cd1c85…提交者 UUID
commitIdentifier9223372036854775807批模式一次性提交
commitKindAPPEND只是追加,无覆盖
timeMillis1763467914504提交瞬间时间戳
totalRecordCount19整张表共 19 行
deltaRecordCount1本次追加 1 行
changelogRecordCount1变更日志里记录了 1 行(update/delete 明细)
watermark-9223372036854775808无事件时间
tagCreateTime2025-11-18 20:00:02.582打标签的瞬间(人眼可读)
tagTimeRetained31536000 s保质期 365 天(快照不会被后台清理)

4. Tag 功能详解

4.1 Tag 的概念

Tag 是 Paimon 中的一个重要功能,它允许用户为表的特定快照创建标签,类似于 Git 中的标签功能。

4.2 Tag 的创建与存储

4.2.1手动创建标签

创建 Tag 时,Paimon 会根据当前快照进行创建:

-- 创建 Tag
CALL sys.create_tag('dwd.source_migration_table', 'tag_10_12', 12, '365d');

-- 查看所有 Tag
SELECT * FROM `source_migration_table$tags`;

Tag 信息存储在表的元数据中,可以通过系统表 table$tags 进行查询。

在这里插入图片描述

4.2.2自动创建标签

Paimon支持在写作任务中自动创建标签。

步骤 1:选择创建模式

您可以通过表选项设置创建模式'tag.automatic-creation'。支持的值包括:

  • process-time根据机器运行时间创建标签。
  • watermark:根据 Sink 输入的水印创建标签。
  • batch在批量处理场景中,当前任务完成后会生成一个标签。

步骤二:选择创建周期

标签生成频率是多少?您可以选择 -1-2``'daily''hourly'`` ‘two-hours’-3 'tag.creation-period'

如果需要等待延迟数据,可以设置延迟时间:'tag.creation-delay'

步骤 3:自动删除标签

您可以配置'tag.num-retained-max'tag.default-time-retained自动删除标签。

例如,配置表格,使其每天 0:10 创建一个标签,最大保留时间为 3 个月:

-- Flink SQL
CREATE TABLE t (
    k INT PRIMARY KEY NOT ENFORCED,
    f0 INT,
    ...
) WITH (
    'tag.automatic-creation' = 'process-time',
    'tag.creation-period' = 'daily',
    'tag.creation-delay' = '10 m',
    'tag.num-retained-max' = '90'
);

INSERT INTO t SELECT ...;

-- Spark SQL

-- Read latest snapshot
SELECT * FROM t;

-- Read Tag snapshot
SELECT * FROM t VERSION AS OF '2023-07-26';

-- Read Incremental between Tags
SELECT * FROM paimon_incremental_query('t', '2023-07-25', '2023-07-26');

4.3 Tag 的功能与应用场景

查询tag对应快照版本的数据:

#查询标签数据必须在批模式下
SET execution.runtime-mode=BATCH;

#查询数据tag_10_12这个tag的数据
SELECT * FROM source_migration_table /*+ OPTIONS('scan.tag-name' = 'tag_10_12') */;

在这里插入图片描述

5. Paimon 与 Hive 查询最新数据对比

5.1 Hive 查询最新数据的传统方式

在 Hive 中,查询最新数据通常需要使用复杂的 SQL 技巧,例如:

-- Hive 查询最新分区数据的传统方式
SELECT COUNT(*) FROM 
( 
    SELECT partition_date, 
        ROW_NUMBER() OVER (PARTITION BY partition_date ORDER BY partition_date DESC) as rank_number 
    FROM dwd_core_enterprises_whitelist_info 
    WHERE partition_date > '2023-01-01' AND partition_date < '2023-12-31'
) a 
WHERE a.rank_number = 1;

Hive 方式的缺点:

  1. 查询复杂度高:需要编写复杂的窗口函数
  2. 性能开销大:需要对全表数据进行排序和分区
  3. 维护困难:SQL 语句难以理解和维护
  4. 实时性差:无法支持实时数据查询

5.2 Paimon 查询最新数据的优势

Paimon 通过快照机制提供了更简单、高效的查询方式:

-- Paimon 查询最新数据(默认行为)
SELECT COUNT(*) FROM dwd_core_enterprises_whitelist_info;

-- Paimon 查询特定时间点的数据(时间旅行)
SELECT COUNT(*) FROM dwd_core_enterprises_whitelist_info 
/*+ OPTIONS('scan.timestamp-millis'='1672531200000') */;

-- Paimon 通过 Tag 查询特定版本数据
SELECT COUNT(*) FROM dwd_core_enterprises_whitelist_info 
/*+ OPTIONS('scan.tag-name'='v1.0') */;

Paimon 方式的优势:

  1. 查询简单直观:无需复杂SQL,直接查询即可获得最新数据
  2. 高性能:利用快照机制直接定位最新数据
  3. 实时性支持:支持流式数据实时查询
  4. 版本控制:内置的时间旅行和Tag功能
  5. 一致性保证:快照机制确保查询结果的一致性

5.3 性能对比分析

特性HivePaimon
查询复杂度高(需要窗口函数)低(直接查询)
查询性能中等(全表扫描)高(快照定位)
实时性不支持支持
版本管理需要外部工具内置支持
数据一致性需要手动保证自动保证
存储效率中等高(LSM结构)

6. 存储效率与技术优势分析

6.1 存储效率优化机制

Paimon 通过多种机制优化存储效率:

6.1.1 数据压缩与合并
  • LSM 树合并操作:定期合并小文件,减少存储碎片
  • 列式存储压缩:Parquet/ORC 格式提供高效的列压缩
  • 增量存储:只存储变更数据,避免全量复制
6.1.2 快照存储优化
  • 共享引用:多个快照共享相同的数据文件引用
  • 增量快照:新快照只记录变更,不复制完整数据
  • 自动清理:过期快照和未被引用的文件自动清理

6.2 技术优势总结

6.2.1 与传统数据湖的对比优势
技术特性传统数据湖Paimon
存储结构文件列表LSM 树
写入性能中等高(顺序写入)
查询性能依赖文件扫描快照定位
实时能力有限完整支持
版本管理外部工具内置 Tag
存储效率中等高(压缩+合并)
6.2.2 架构创新点
  1. LSM 树应用:将 LSM 树引入数据湖存储,优化写入性能
  2. 快照机制:轻量级的快照管理,支持时间旅行查询
  3. Tag 系统:Git-like 的版本标签管理
  4. 流批一体:同一存储支持流处理和批处理

7. 实际应用场景

7.1 数据湖架构升级

从传统的 Hive 数据仓库升级到 Paimon 数据湖,可以显著提升:

  • 查询性能:快照机制减少数据扫描量
  • 开发效率:简化数据查询逻辑
  • 运维成本:自动化的快照和版本管理

7.2 实时数据分析

Paimon 支持流批一体架构,适用于:

  • 实时报表:分钟级甚至秒级的数据更新
  • 实时监控:业务指标的实时计算和展示
  • 实时推荐:基于最新用户行为的推荐系统

7.3 数据治理与合规

通过 Tag 和快照机制,Paimon 支持:

  • 数据审计:完整的数据变更历史记录
  • 合规检查:标记符合法规的数据版本
  • 数据质量:版本化的数据质量检查点

8. 总结

Apache Paimon 通过其创新的存储结构和快照机制,为大数据处理带来了革命性的改进:

8.1 核心技术优势

  1. 存储效率:LSM 树结构和数据压缩优化存储空间,快照存储不会翻倍增长
  2. 查询性能:快照机制显著提升查询效率,避免复杂 SQL
  3. 版本管理:Tag 功能提供灵活的数据版本控制
  4. 实时能力:支持流批一体的实时数据处理
  5. 架构创新:三层架构设计,与 Iceberg/Hudi/Delta 有明显区别

8.2 底层技术原理

  • LSM 树存储:基于日志结构合并树的存储架构
  • 快照机制:轻量级的版本管理,支持时间旅行
  • Tag 系统:Git-like 的标签管理,存储在 metadata 目录
  • 数据组织:基于哈希的分桶存储,优化查询性能

8.3 应用价值

对于需要处理大规模数据并追求实时性和查询性能的应用场景,Paimon 是一个值得考虑的优秀选择。特别是在以下场景下,Paimon 的优势尤为明显:

  • 频繁查询最新数据:相比 Hive 的复杂窗口函数,Paimon 提供直接查询
  • 时间旅行查询:内置支持历史数据查询
  • 严格版本控制:Tag 系统确保数据版本一致性
  • 实时数据处理:流批一体架构支持实时应用

Paimon 的创新存储架构和高效查询机制,为现代数据湖建设提供了强有力的技术支撑。

9. 初学者实践指南

9.1 快速开始:第一个Paimon项目

9.1.1 环境准备

系统要求:

  • Java 8 或更高版本
  • Apache Flink 1.14+(推荐)
  • Maven 或 Gradle 构建工具

依赖配置(Maven):

<dependency>
    <groupId>org.apache.paimon</groupId>
    <artifactId>paimon-flink</artifactId>
    <version>1.0.0</version>
</dependency>
9.1.2 创建第一个Paimon表

步骤1:定义表结构

-- 创建用户行为表
CREATE TABLE user_behavior (
    user_id BIGINT,
    behavior_type STRING,
    timestamp TIMESTAMP(3),
    item_id BIGINT,
    category_id BIGINT,
    WATERMARK FOR timestamp AS timestamp - INTERVAL '5' SECOND
) WITH (
    'connector' = 'paimon',
    'path' = 'file:///tmp/user_behavior',
    'auto-create' = 'true'
);

步骤2:插入测试数据

INSERT INTO user_behavior VALUES 
(1001, 'click', TIMESTAMP '2024-01-01 10:00:00', 2001, 3001),
(1001, 'buy', TIMESTAMP '2024-01-01 10:01:00', 2001, 3001),
(1002, 'click', TIMESTAMP '2024-01-01 10:02:00', 2002, 3002);

步骤3:查询数据

-- 查询最新数据
SELECT * FROM user_behavior;

-- 按用户分组统计
SELECT user_id, COUNT(*) as click_count 
FROM user_behavior 
WHERE behavior_type = 'click'
GROUP BY user_id;

9.2 常用操作示例

9.2.1 数据写入操作

批量写入示例:

// Java代码示例:批量写入Paimon表
TableEnvironment tableEnv = TableEnvironment.create(EnvironmentSettings.inStreamingMode());

// 创建Paimon表
tableEnv.executeSql("
    CREATE TABLE user_orders (
        order_id BIGINT,
        user_id BIGINT,
        amount DECIMAL(10,2),
        order_time TIMESTAMP(3)
    ) WITH (
        'connector' = 'paimon',
        'path' = 'file:///tmp/user_orders',
        'auto-create' = 'true'
    )
");

// 批量插入数据
tableEnv.executeSql("
    INSERT INTO user_orders VALUES
    (1, 1001, 99.99, TIMESTAMP '2024-01-01 09:00:00'),
    (2, 1002, 199.99, TIMESTAMP '2024-01-01 09:01:00'),
    (3, 1001, 49.99, TIMESTAMP '2024-01-01 09:02:00')
");

流式写入示例:

// 从Kafka流式写入Paimon
Table kafkaSource = tableEnv.from("kafka_source");
Table paimonSink = kafkaSource.select($("user_id"), $("behavior"), $("timestamp"));
paimonSink.executeInsert("user_behavior");
9.2.2 数据查询操作

时间旅行查询:

-- 查询1小时前的数据快照
SELECT * FROM user_behavior FOR SYSTEM_TIME AS OF TIMESTAMP '2024-01-01 09:00:00';

-- 查询特定标签版本的数据
SELECT * FROM user_behavior FOR SYSTEM_VERSION AS OF 'v1.0';

增量查询:

-- 查询最近5分钟的增量数据
SELECT * FROM user_behavior 
WHERE timestamp >= NOW() - INTERVAL '5' MINUTE;
9.2.3 表管理操作

创建标签:

-- 为当前快照创建标签
CALL sys.create_tag('user_behavior', 'v1.0', 'Initial version with user behavior data');

查看表信息:

-- 查看表结构
DESCRIBE user_behavior;

-- 查看快照历史
SELECT * FROM user_behavior$snapshots;

-- 查看标签信息
SELECT * FROM user_behavior$tags;

数据清理:

-- 清理过期快照(保留最近7天)
CALL sys.expire_snapshots('user_behavior', 7);

9.3 最佳实践建议

9.3.1 表设计最佳实践
  1. 合理设置桶数量:根据数据量设置合适的桶数(通常4-32个)
  2. 选择合适的主键:为频繁查询的字段设置主键
  3. 设置合理的分区:按时间或业务维度分区
  4. 配置适当的TTL:根据业务需求设置数据保留时间
9.3.2 性能优化建议
  1. 批量写入:尽量使用批量写入而非单条插入
  2. 预聚合:对统计类查询进行预聚合
  3. 索引优化:为查询条件字段创建合适的索引
  4. 内存调优:根据数据量调整内存配置
9.3.3 运维监控建议
  1. 监控快照数量:定期清理过期快照
  2. 监控存储空间:关注数据文件增长情况
  3. 备份重要标签:对重要版本创建标签备份
  4. 定期健康检查:检查表状态和性能指标

9.4 故障排除与常见问题

9.4.1 常见错误及解决方案

问题: 无法连接到Paimon表
解决方案:

  • 检查表路径是否正确
  • 确认表是否存在(auto-create设置为true)
  • 检查文件系统权限

问题: 查询速度慢
解决方案:

  • 检查是否设置了合适的主键
  • 考虑增加桶数量
  • 优化查询条件,避免全表扫描

问题: 存储空间增长过快
解决方案:

  • 设置合理的快照保留时间
  • 定期清理过期数据
  • 考虑数据压缩选项
9.4.2 调试技巧

日志分析:
启用详细日志来诊断问题:

# 在log4j.properties中设置
log4j.logger.org.apache.paimon=DEBUG

系统表查询:
使用系统表获取内部状态:

-- 查看表统计信息
SELECT * FROM user_behavior$schemas;
SELECT * FROM user_behavior$snapshots;
SELECT * FROM user_behavior$manifests;

性能分析:
使用EXPLAIN分析查询计划:

EXPLAIN PLAN FOR SELECT * FROM user_behavior WHERE user_id = 1001;

9.5 进阶学习资源

9.5.1 官方文档
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值