Apache Parquet 1.18 配置参数详解
详解 Apache Parquet 1.18.1(Java 版 parquet-mr)在 AvroParquetWriter/Hadoop Configuration 中的常用配置参数——行组大小、页大小、字典编码、压缩编解码器、writer version,Hadoop 依赖配置,以及大数据分析场景的生产配置模板(标注数据量/内存/磁盘),已在 Ubuntu 22.04.5 实测
Apache Parquet 1.18 配置参数详解
目标:系统详解 Apache Parquet 1.18.1(Java 版 parquet-mr)在 Java 应用中的配置参数——行组(RowGroup)大小、页(Page)大小、字典编码开关、压缩编解码器、writer version,以及 Hadoop 依赖配置,并给出标注数据量/内存/磁盘场景的生产配置模板。参数含义、默认值与示例均在 Ubuntu 22.04.5 + JDK 17 环境实测通过。
一、环境信息
| 项目 | 实测值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS |
| Java | OpenJDK 17.0.20.1 |
| Maven | Apache Maven 3.6.3 |
| Parquet | parquet 1.18.1(parquet-hadoop / parquet-avro) |
| Hadoop 依赖 | hadoop-client 3.3.6 |
| 写入 API | AvroParquetWriter + AvroParquetReader |
| 输出文件 | /tmp/output.parquet(10 条 × 3 列,937 字节) |
二、前置条件
已按《Ubuntu 22.04 安装 Apache Parquet 1.18 指南》准备好工程环境(OpenJDK 17 + Maven + hadoop-client 3.3.6)。本文示例基于一个可运行的 Maven 工程(含 demo.Person 的 Avro schema,name/age/hired),具体 pom 与源码见《Apache Parquet 1.18 构建并运行示例数据存储应用指南》篇,此处聚焦参数说明,示例命令均可独立执行。
三、参数查看与修改方式
Parquet 1.18(Java 版)没有类似服务端配置文件的「配置文件」,其参数通过两种方式传入:
- 写入器 builder 链式设置:使用
AvroParquetWriter.builder(path)、ExampleParquetWriter等,方法名即参数名(如withRowGroupSize、withPageSize、withCompressionCodec、withDictionaryEncoding)。 - Hadoop
Configuration键值对:通过conf.set("key", "value")或 builder 的withConf(conf)传入,覆盖默认行为。
验证当前生效参数值:用 ParquetFileReader.readFooter(Configuration, Path) 读取 footer 元数据,可看到 created_by(writer version)、rowGroup/columnChunk 统计、写入的压缩与编码信息(见《Apache Parquet 1.18 构建并运行示例数据存储应用指南》篇 6.2 回显)。
四、参数总览
| 参数(builder)/ 键(Configuration) | 默认值 | 说明 |
|---|---|---|
| withRowGroupSize / parquet.block.size | 134217728(128MB) | 每个 RowGroup 目标大小 |
| withPageSize / parquet.page.size | 1048576(1MB) | 数据页目标大小(压缩前) |
| withDictionaryPageSize / parquet.dictionary.page.size | 1048576(1MB) | 字典页上限 |
| withCompressionCodec / parquet.compression | SNAPPY | 列压缩编解码器 |
| withDictionaryEncoding / parquet.enable.dictionary | true | 是否启用字典编码 |
| withWriterVersion / parquet.writer.version | PARQUET_1_0 | 写入格式版本 |
| withConf / (Hadoop Configuration) | 由应用提供 | 底层 Hadoop/文件系统配置 |
| withValidation / parquet.validation | false | 写入时是否校验 |
⚠️ 说明:以上默认值取自 parquet 1.18.1 与 Hadoop 的常见默认;不同版本可能略有差异,正式使用前请以
mvn dependency:tree关联的 parquet 版本 + JavaDoc 为准。
五、核心参数分类详解
5.1 行组(RowGroup)相关
withRowGroupSize / parquet.block.size(行组大小)
- 含义:单个 RowGroup 的目标字节大小。RowGroup 是并行读取与存储对齐的基本单元,包含一批行的全部列。
- 默认值:134217728(128MB)。
- 影响:行组过小(如几十 KB)会导致大量小 RowGroup、读放大与查询性能差;过大则单批内存占用高、flush 不及时。写入达到该上限时会触发一次行组落盘。
- 示例:
AvroParquetWriter.<GenericRecord>builder(path)
.withRowGroupSize(134217728) // 128MB
.build();
实测:10 条小数据仅 1 个 RowGroup(bytes=223),默认一行批写入满后形成单 RowGroup;数据量达到几十 MB 后会自动切分。
5.2 页(Page)相关
withPageSize / parquet.page.size(数据页大小)
- 含义:每个数据页(DataPage)的目标大小(未压缩字节数)。页是编码与压缩的最小单元,读取按页解码。
- 默认值:1048576(1MB)。
- 影响:页过小增加页头与校验开销;页过大会让只读局部数据的查询加载过多无用数据。列裁剪按 columnChunk,谓词下推按页统计(min/max)。
- 示例:
.withPageSize(1048576) // 1MB
withDictionaryPageSize / parquet.dictionary.page.size(字典页大小)
- 含义:字典页最多可用的字节数,超过该上限后不再为后续值继续建字典。
- 默认值:1048576(1MB)。
- 示例:
.withDictionaryPageSize(1048576)
5.3 字典编码
withDictionaryEncoding / parquet.enable.dictionary(是否启用字典编码)
- 含义:是否对列先建立「值→字典 id」映射,再以 RLE/bit-packing 存储字典 id。低基数(重复多)的列收益巨大。
- 默认值:true。
- 影响:低基数列(如部门、状态、性别)建议开启;高基数列(UUID、长文本、每行唯一)字典本身开销大,可关闭。
- 示例:
// 关闭字典编码(适合高基数列)
.withDictionaryEncoding(false)
💡 说明:字典编码与 RLE(run-length/bit-packing)是 parquet 页内最常见的两种编码;实测中 3 个 columnChunk 各 10 值,高重复值场景下文件可显著压缩。
5.4 压缩编解码器
withCompressionCodec / parquet.compression(压缩编解码器)
- 含义:列数据使用的压缩算法。
- 默认值:SNAPPY。
- 可选值:UNCOMPRESSED、SNAPPY、GZIP、ZSTD、LZ4 等(需加载对应后端的 Java 实现,如
zstd-jni)。 - 权衡:
| 编解码器 | 压缩率 | CPU 开销 | 适用 |
|---|---|---|---|
| SNAPPY | 中等 | 低 | 默认,平衡 |
| GZIP | 高 | 高 | 追求压缩比 |
| ZSTD | 高且快 | 中 | 推荐(大文件) |
| UNCOMPRESSED | 无 | 无 | 磁盘充足、追求最高吞吐 |
- 示例:
import org.apache.parquet.hadoop.metadata.CompressionCodecName;
.withCompressionCodec(CompressionCodecName.ZSTD)
5.5 writer version 与元数据
withWriterVersion / parquet.writer.version(写入格式版本)
- 含义:控制写入器采用的 parquet 格式版本(对应 footer 中 created_by 的格式语义、编码选用范围)。
- 默认值:PARQUET_1_0(
ParquetWriter.DEFAULT_WRITER_VERSION)。 - 常用值:PARQUET_1_0 / PARQUET_2_0。2.0 允许更丰富的 encoding(如柱状 DELTA、RLE_DICTIONARY 数据页),但老读取器可能不识别。
- footer 中 created_by 记录写入器版本字符串,本环境实测为:
created_by=parquet-mr version 1.18.1 (build 7c22cdba6792fa29c5bda74bf1f866a08d7572a9)
- 示例:
.withWriterVersion(org.apache.parquet.hadoop.ParquetWriter.DEFAULT_WRITER_VERSION)
footer 元数据(自描述 schema)
- parquet 文件末尾 footer 存 Thrift 元数据:schema + created_by + writer model + 各 RowGroup/列统计(min/max/null 数),支撑谓词下推与列裁剪,读取无需外部 schema 文件。
- 本示例经 Avro writer model 写出,footer metadata 含
parquet.avro.schema与writer.model.name=avro。
5.6 Hadoop 依赖配置
Parquet 读写依赖 Hadoop 的 Configuration 与 Path 抽象。配置要点:
- 依赖坐标:引入
org.apache.hadoop:hadoop-client:3.3.6(JDK 17 兼容);版本过低(2.x)或缺省会抛FileSystem/ConfigurationException。 - Configuration 传递:写入器 builder 用
.withConf(conf)传入new Configuration();读取器可直接AvroParquetReader.builder(path).build()或同样传 conf。 - 常用键:
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "file:///"); // 本地文件系统
conf.set("parquet.compression", "ZSTD"); // 默认压缩
conf.set("parquet.block.size", "134217728"); // 行组 128MB
- readFooter 参数:
ParquetFileReader.readFooter(Configuration, Path)第二个参数传 HadoopPath,勿传HadoopInputFile(否则编译报 no suitable method found)。
六、生产配置模板
以下模板面向「大数据分析场景」,给出数据量 / 内存 / 磁盘前提与对应参数建议。
6.1 OLAP 大数据分析(列投影 + 谓词下推)
- 适用场景:数仓 ODS/ADS 层、BI 报表、Spark/Trino 扫描分析;单文件 GB~几十 GB,服务器 32GB 内存,NVMe SSD。
- 参数建议:
AvroParquetWriter.<GenericRecord>builder(path)
.withSchema(schema)
.withConf(conf)
.withRowGroupSize(134217728) // 128MB,与 HDFS 块/并行读取对齐
.withPageSize(1048576) // 1MB
.withDictionaryPageSize(1048576) // 1MB
.withCompressionCodec(CompressionCodecName.ZSTD) // 大文件高压缩且快
.withDictionaryEncoding(true) // 低基数列默认启用字典
.build();
- JVM 构建/运行堆(本专栏 256–512MB 约定):
MAVEN_OPTS="-Xms256m -Xmx512m" mvn clean package -DskipTests
java -Xms256m -Xmx512m -jar target/parquet-demo-1.0.0.jar
- 验证生效:
jps -v应看到-Xms256m -Xmx512m。
6.2 高基数列 + 大字典场景
- 适用场景:含 UUID / 长文本 / 时间日志等高基数列,内存 64GB,SATA HDD。
- 建议:对高基数列关闭字典避免字典膨胀,改用 SNAPPY/GZIP;行组可适当调大到 256MB 减少小文件。
.withCompressionCodec(CompressionCodecName.GZIP)
.withDictionaryEncoding(false) // 高基数列关闭字典
💡 说明:是否开启字典需权衡——低基数列开字典(压缩比高、读快),高基数列关字典(省字典构建与存储)。可用
mvn dependency:tree核对版本后,用《Apache Parquet 1.18 常用工具与 API 详解》篇的 footer 读取验证实际写入参数。
⚠️ 注意:生产环境请先在小数据集上验证参数对文件大小、读写性能与兼容性的影响,再推广到全量;跨引擎读取时注意 writer version 与编码的向前兼容。
七、常见问题
Q1:写出的 parquet 没有按预期分多个 rowGroup
rowGroup 数受 withRowGroupSize 与数据量共同决定,总数据量不足一个 rowGroup 上限时就只有 1 个 rowGroup(正常)。要强制多行组需让总量达到数百 MB 或手动控制 flush 批。
Q2:parquet.compression 设 ZSTD 但运行报找不到编解码器
ZSTD 需要 com.github.luben:zstd-jni 后端实现。在 pom 加入 org.apache.parquet:parquet-format-structures 所在版本的 zstd-jni 依赖,或确认 shade jar 已包含。
Q3:改参数后 footer 里 created_by 不变
created_by 只记录 parquet 写入器版本(1.18.1),不含用户自定义参数;参数效果体现在 RowGroup/列块大小、压缩类型与 schema 统计上。用 footer 看 columns 的统计(min/max/null 数)与压缩即可验证。
Q4:readFooter 传 HadoopInputFile 编译报 no suitable method found
1.x 的 readFooter(Configuration, Path) 只接受 Hadoop Path,改用 org.apache.hadoop.fs.Path。
Q5:hadoop 版本过低抛 FileSystem/ConfigurationException
将 hadoop-client 固定为 3.3.6(JDK 17 兼容),mvn clean package 后重试。
Q6:JDK 17 运行部分反射 API 报 InaccessibleObjectException
按需在运行命令或 JAVA_TOOL_OPTIONS/MAVEN_OPTS 追加 --add-opens;本专栏示例不触发,无需处理。
八、参考链接
- Apache Parquet 官方:https://parquet.apache.org/
- parquet-java JavaDoc:https://javadoc.io/doc/org.apache.parquet/parquet-hadoop/latest/index.html
- parquet-format 规范:https://github.com/apache/parquet-format
- Hadoop Configuration:https://hadoop.apache.org/docs/r3.3.6/api/org/apache/hadoop/conf/Configuration.html