Java 操作 Parquet 文件

目录

  1. 简介
  2. Parquet 文件格式概述
  3. Java 读取和写入 Parquet
  4. 常见实践
  5. 最佳实践
  6. 小结
  7. 参考资料

简介

Parquet 是一种列式存储格式,广泛应用于大数据处理,如 Hadoop、Spark、Flink 等。它相比传统的行存储格式(如 CSV、JSON),能够大幅减少存储空间并提高查询性能。Java 作为主流开发语言之一,Apache 提供了相应的 API 来操作 Parquet 文件。

本文将介绍如何在 Java 中读写 Parquet 文件,并探讨其最佳实践。


Parquet 文件格式概述

Parquet 采用列式存储,适用于高效的查询和数据压缩。其主要特点包括:

  • 列式存储:数据按列存储,适合分析型查询。
  • 高效压缩:支持多种压缩算法,如 Snappy、Gzip 等。
  • 支持多种数据类型:包括基本类型(整数、浮点数、布尔值等)以及复杂类型(数组、嵌套结构等)。
  • Schema 演进:支持 schema 变更,例如新增列。

Java 读取和写入 Parquet

依赖库

要在 Java 项目中使用 Parquet,需要添加以下 Maven 依赖:

<dependencies>
    <!-- Parquet 依赖 -->
    <dependency>
        <groupId>org.apache.parquet</groupId>
        <artifactId>parquet-avro</artifactId>
        <version>1.12.3</version>
    </dependency>

    <!-- Hadoop 依赖 -->
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>3.3.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-mapreduce-client-core</artifactId>
        <version>3.3.1</version>
    </dependency>
</dependencies>

写入 Parquet 文件

使用 parquet-avro 生成 Parquet 文件,通常借助 AvroParquetWriter。示例如下:

import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.parquet.hadoop.ParquetWriter;
import org.apache.parquet.hadoop.metadata.CompressionCodecName;
import org.apache.parquet.avro.AvroParquetWriter;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;

public class ParquetWriteExample {
    public static void main(String[] args) throws Exception {
        // 定义 Avro Schema
        String schemaJson = "{"
                + "\"type\": \"record\","
                + "\"name\": \"User\","
                + "\"fields\": ["
                + "  {\"name\": \"id\", \"type\": \"int\"},"
                + "  {\"name\": \"name\", \"type\": \"string\"}"
                + "]}";
        Schema schema = new Schema.Parser().parse(schemaJson);

        // 创建 ParquetWriter
        Path file = new Path("users.parquet");
        try (ParquetWriter<GenericRecord> writer = AvroParquetWriter.<GenericRecord>builder(file)
                .withSchema(schema)
                .withCompressionCodec(CompressionCodecName.SNAPPY)
                .withConf(new Configuration())
                .build()) {
            
            // 创建数据
            GenericRecord record = new GenericData.Record(schema);
            record.put("id", 1);
            record.put("name", "Alice");
            writer.write(record);

            record.put("id", 2);
            record.put("name", "Bob");
            writer.write(record);
        }

        System.out.println("Parquet 文件写入完成!");
    }
}

读取 Parquet 文件

使用 ParquetReader 读取 Parquet 文件:

import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.parquet.avro.AvroParquetReader;
import org.apache.parquet.hadoop.ParquetReader;
import org.apache.hadoop.fs.Path;

public class ParquetReadExample {
    public static void main(String[] args) throws Exception {
        Path file = new Path("users.parquet");

        try (ParquetReader<GenericRecord> reader = AvroParquetReader.<GenericRecord>builder(file).build()) {
            GenericRecord record;
            while ((record = reader.read()) != null) {
                System.out.println(record);
            }
        }
    }
}

常见实践

1. 选择合适的压缩格式

  • Snappy:适用于快速压缩和解压缩,适合大多数场景。
  • Gzip:压缩率高,但解压速度较慢,适合长时间存储数据。
  • LZO:适用于 Hadoop 生态,但需要额外的 native 库支持。

2. 适当的 Schema 设计

  • 避免嵌套过深的数据结构,减少读取开销。
  • 根据查询需求优化数据类型,例如日期存储为 int 以减少存储占用。

在 Spark 中,可以直接使用:

val df = spark.read.parquet("users.parquet")
df.show()

最佳实践

  • 使用 Snappy 压缩:对于大多数查询场景,Snappy 提供良好的性能和存储优化。
  • 合理的列存储:尽量减少不必要的列,以提高查询效率。
  • 并行写入:如果数据量大,建议使用 Hadoop/Spark 的 parquet-mr 进行并行写入,提高吞吐量。
  • Schema 兼容性:设计时考虑向前/向后兼容,避免频繁的 Schema 变更导致解析失败。

小结

本文介绍了 Parquet 文件的基本概念,并详细讲解了如何在 Java 中使用 parquet-avro 进行数据的读写。通过合理选择压缩方式、优化 Schema 以及结合大数据框架使用,可以充分发挥 Parquet 的优势,提高数据分析的效率。


参考资料

posted @   hyzz123  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示