讲讲Paimon的文件布局结构
在 Apache Paimon 中,表的所有文件都存储在一个统一的基准目录(Base Directory,通常在 warehouse/database_name/table_name 下)下。Paimon 的底层文件布局采用了高度解耦和分层的架构设计。
通过从 Paimon 的 snapshot 目录开始,读取器(Reader)可以递归地访问到表的所有元数据,进而找到真实的底层物理数据文件。
一、 Paimon 文件布局整体结构树
一个典型分区表的底层目录与文件结构如下所示:
plaintext
warehouse (或者是 warehouse 的根目录)
└── default.db (数据库目录)
└── my_table (表目录)
├── schema (Schema 目录)
│ ├── schema-0 (JSON)
│ └── schema-1 (JSON)
├── snapshot (Snapshot 目录)
│ ├── EARLIEST (快照起点 Hint 文件)
│ ├── LATEST (快照终点 Hint 文件)
│ ├── snapshot-1 (JSON)
│ └── snapshot-2 (JSON)
├── manifest (Manifest 目录)
│ ├── index-manifest-xxxx (可选)
│ ├── manifest-xxxx-0 (Avro)
│ ├── manifest-list-xxxx-0 (Avro,当前快照的基础清单列表)
│ └── manifest-list-xxxx-1 (Avro,当前快照产生的增量清单列表)
├── index (Index 目录 - 可选)
│ └── index-xxxx-0
└── [partition_directory] (分区目录,如 dt=20260521)
└── bucket-0 (Bucket 目录,LSM 树最小单元)
├── data-xxxx-0.parquet (物理数据文件)
├── changelog-xxxx-0.parquet (Changelog 增量变更文件)
└── xxx.dv (MOW模式下的删除向量文件)
二、 核心目录与文件详解
1. Schema 目录 (schema/)
- 文件命名与格式:命名为
schema-N(自 0 开始递增),格式为 JSON。 - 内容与作用:存储表的结构定义版本。每当对表执行
ALTER TABLE演进 Schema 或更新参数(Options)时,都会在此目录下生成一个版本递增的新 JSON 文件。- 核心字段:
fields(包含为每一列分配的唯一自增 id,以此支持字段重命名、增删等 Schema Evolution 演进);partitionKeys(分区字段);primaryKeys(主键定义);options(表参数选项)。
- 核心字段:
- 保留机制:历史 schema 文件不能被物理删除,因为有些存量的 Data Files 依然需要依赖旧 schema 才能正确被解析。
2. Snapshot 目录 (snapshot/)
- 文件命名与格式:命名为
snapshot-N(自 1 开始连续递增),格式为 JSON。 - 内容与作用:快照代表了表在特定提交时间点的完整数据集视图。它是整个读取流程的初始入口。
EARLIEST与LATEST:这两个是快照版本提示文件(Hint Files)。它们以简化的文本记录当前的最老/最新快照 ID,供 Reader 启动时迅速定位。- 快照 JSON 字段:包含当前快照绑定的
schemaId、当前快照的数据状态由哪些元数据组成(baseManifestList基础清单、deltaManifestList增量变更清单、changelogManifestList增量变更 Changelog 清单)、提交类型(commitKind,如 APPEND/COMPACT 等)、水印(watermark)等。
3. Manifest 目录 (manifest/)
- 文件命名与格式:包含
manifest-list与manifest文件,格式为 Avro。 - 清单列表(Manifest List):
- 作用:它是连接快照和具体清单文件之间的桥梁。
- 内部结构:存储了一个或多个 Manifest 物理文件的元数据信息(文件名、文件大小、新增/逻辑删除的文件个数),同时维护了
_PARTITION_STATS(分区级统计指标,如分区字段的最大/最小值等)。在查询时,Reader 仅通过读取轻量级的 Manifest List,即可直接根据分区范围过滤掉无关的 Manifest 文件。
- 清单文件(Manifest File):
- 作用:描述具体的底层物理数据文件(Data File)和增量变更文件(Changelog File)的变化明细。
- 内容:详细记录了每一次提交对应哪些 LSM 数据文件是新增的(ADD 状态),哪些数据文件已被 compact 清除/逻辑删除(DELETE 状态)。
4. Index 目录 (index/ - 可选)
- 内容与作用:存储哈希桶的全局索引文件(Global Index),一般在启用主键表的跨分区去重(Cross Partition Upsert)或特定的动态桶(Dynamic Bucket)模式时生成,用以加速主键到 Bucket 映射关系的定位。
5. 分区与 Bucket 目录(Data Directories)
Paimon 的实际数据存储物理路径位于分区和 Bucket 子目录下。
- 分区划分:采用与 Apache Hive 相同的
key=value目录结构隔离物理文件。如果表未定义分区,则所有数据都在表根目录下。 - Bucket 划分:在每个分区(或未分区表的根目录)下,根据配置分成若干个
bucket-N子目录。每一个 Bucket 对应一个独立的读写切片,是一个独立的 LSM 树存储结构。 - Bucket 内部存储的文件类型:
- Data Files(物理数据文件):格式通常为
data-${uuid}-${id}.${format},支持 Parquet(推荐列存)、ORC、Avro 等文件格式。- 主键表数据文件:除常规字段列外,还会物理存储额外的隐式元数据列(如主键前缀
_KEY_列、_VALUE_KIND行为标志、_SEQUENCE_NUMBER变更序号),用以支持 LSM 的合并引擎。 - 无主键表数据文件:只存储普通的业务列数据。
- 主键表数据文件:除常规字段列外,还会物理存储额外的隐式元数据列(如主键前缀
- Changelog Files(增量变更文件):结构与普通数据文件完全相同,仅在表配置了相应的
changelog-producer时生成,存储准确的增量变更流。 - Deletion Vectors Files(删除向量文件):在 Merge-on-Write 模式(MOW)下,如果记录被物理更新或删除,系统会在当前 Bucket 内生成对应的
.dv文件,记录具体文件里被删除数据行的 Offset,避免高成本的多路归并。
- Data Files(物理数据文件):格式通常为