文件格式对比:Avro / Parquet / ORC
概述
数据落地 HDFS,用什么文件格式直接决定存储成本、读写速度与压缩率。Hadoop 生态三巨头:Avro 是行式序列化格式,Parquet 与 ORC 是列式存储格式。本文拆解各自原理,给出压缩与 Schema 演化对比,并给出选型建议。
一、为什么需要专门的文件格式
文本文件(CSV/JSON)简单但效率低:无类型、无压缩、列式场景要全量扫描。面向大数据分析,理想格式应具备:
| 能力 | 说明 |
|---|---|
| 类型化 | 数值/日期有明确类型,查询引擎可优化 |
| 高压缩 | 按列压缩,同列数据相似度高 |
| 列裁剪 | 只读需要的列,减少 IO |
| Schema 演化 | 表结构变化不影响旧数据 |
| 谓词下推 | 在读取层过滤,减少数据量 |
Avro、Parquet、ORC 分别从"序列化协议"与"存储布局"两个方向解决这些问题。
二、Avro:行式序列化
2.1 设计理念
Avro 最初为 Hadoop 生态提供远程调用与数据序列化方案(替代 Thrift/Protobuf),核心特点是模式即数据:每个文件自带 Schema,读取方无需外部协议文件。
2.2 数据布局
Avro 文件 = 文件头(Schema JSON + 元数据)+ 多个数据块
每个数据块 = 若干记录,行式顺序存储行式存储的优点:整行读写友好,适合数据逐条序列化的流式场景(如 Kafka、Flume、日志采集)。
2.3 Schema 演化
Schema 演化是 Avro 的招牌能力,通过"写模式 → 读模式"映射实现:
- 新增字段:读模式带默认值,旧数据自动补默认值。
- 删除字段:读模式忽略多余字段。
- 类型变更:支持受控的类型提升(如 int → long)。
{
"type": "record",
"name": "Order",
"fields": [
{"name": "id", "type": "long"},
{"name": "amount", "type": "double", "default": 0.0}
]
}旧文件没有 amount 字段,读取时自动填 0.0,无需重写历史数据。
2.4 适用场景
| 场景 | 说明 |
|---|---|
| Kafka 消息序列化 | 配合 Schema Registry 做兼容性管理 |
| 流式数据落地 | Flume/Kafka Connect 写入的日志类数据 |
| 通用 RPC | 跨语言数据传输 |
三、Parquet:列式存储
3.1 设计理念
Parquet 源自 Dremel 论文,专为"按列分析"设计,支持复杂嵌套结构(Map/Array/Struct),是 Spark 生态的默认列式格式。
3.2 数据布局
Parquet 文件 = Footer(元数据 + 各列块索引)+ 多个 Row Group
每个 Row Group 内按列存储,列分页(Page)后压缩| 特性 | 说明 |
|---|---|
| 列裁剪 | 只读取查询涉及的列,省 IO |
| 谓词下推 | 扫描列数据时直接过滤不满足条件的行组 |
| 嵌套支持 | 通过重复级别(repetition level)与定义级别(definition level)表达嵌套结构 |
| 字典编码 | 低基数列(如状态、性别)用字典压缩,效果极好 |
| 文件级统计 | Footer 记录每列 min/max,支持行组级跳过 |
3.3 与 Parquet 配合的生态
Parquet 由 Apache 孵化,Spark、Hive、Impala、Presto/Trino、Flink、DuckDB 全部原生支持,是"格式中立、生态最广"的选择。
四、ORC:专为 Hive 优化的列式存储
4.1 设计理念
ORC(Optimized Row Columnar)由 Hive 团队打造,比 Parquet 更早深度融入 Hive,在 Hive 场景下性能表现突出。
4.2 数据布局
ORC 文件 = Footer(表级统计)+ Stripe(条带,约 64MB~256MB)
每个 Stripe = 列数据(按列分块)+ Index Data(各列 min/max 索引)| 特性 | 说明 |
|---|---|
| Stripe 索引 | 每列记录 min/max,查询跳过无关条带 |
| 轻量索引 | 支持行组级索引,谓词下推更细 |
| ACID 支持 | ORC 是 Hive 事务表(ACID)的底层格式 |
| 压缩友好 | 默认 ZLIB/SNAPPY,对数值类型压缩率高 |
4.3 局限
- 嵌套类型支持不如 Parquet 通用,跨引擎兼容性略弱。
- 强绑定 Hive 生态,Spark/Presto 也支持但优化深度弱于 Parquet。
五、三者对比
5.1 总览表
| 维度 | Avro | Parquet | ORC |
|---|---|---|---|
| 存储布局 | 行式 | 列式 | 列式(条带) |
| 设计目标 | 序列化协议 | 通用分析 | Hive 分析 |
| Schema 演化 | 原生支持(写/读模式映射) | 支持(需兼容规则) | 支持(Hive 层面) |
| 嵌套结构 | 支持 | 支持(Dremel 模型) | 支持 |
| 压缩效果 | 一般(行式) | 好 | 好 |
| 谓词下推 | 无 | 行组级 | 条带 + 行组级 |
| 整行读写 | 最快 | 较慢 | 较慢 |
| 生态 | Kafka/流式、通用 RPC | Spark/Presto/Impala 最广 | Hive 最强 |
| ACID 事务表 | 不支持 | 不支持 | Hive 支持 |
5.2 压缩对比要点
| 压缩算法 | 特点 | 常用场景 |
|---|---|---|
| Snappy | 压缩快、解压快,压缩率中等 | 计算密集的列式存储(Parquet/ORC 默认之一) |
| Gzip/ZLIB | 压缩率高、速度慢 | 归档类、压缩比优先 |
| ZSTD | 平衡压缩率与速度,现代引擎优选 | Spark/Flink/ClickHouse 普遍支持 |
| LZ4 | 极快,压缩率低 | 日志、流式场景 |
列式 + 高压缩率(ZSTD/Gzip)+ 字典编码的组合,通常能把文本数据的存储降到 1/10 以下。
5.3 Schema 演化对比
- Avro:演化规则最完整(新增/删除/默认值/类型提升),是 Schema Registry 的事实标准。
- Parquet:支持增加列、重命名(较新版本),需遵循 Hive 兼容规则。
- ORC:演化能力由 Hive 层提供,配合 Hive DDL 的
ALTER TABLE使用。
六、选型指南
| 场景 | 推荐 | 理由 |
|---|---|---|
| Kafka 消息 / 流式序列化 | Avro + Schema Registry | 演化强、跨语言 |
| Spark 离线分析 ODS/DWD | Parquet | 生态最广、嵌套与下推成熟 |
| Hive 数仓 ADS / 事务表 | ORC | Hive 优化最深、ACID 支持 |
| 日志原始落地 | Snappy+文本 或 Avro | 写入吞吐优先 |
| 跨引擎共享数据湖 | Parquet | Iceberg/Delta/Hudi 默认首选 |
实践建议:离线段用 Parquet + Snappy/ZSTD,Hive 事务场景用 ORC,消息传输用 Avro,避免同一条数据链路混用过多格式。