You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark写入Parquet触发java.io.IOException,如何无错写入Hive表?

问题描述

执行Spark写入Parquet格式Hive表时抛出如下异常:

java.io.IOException: Null or empty fields is found
    at org.apache.parquet.crypto.CryptoMetadataRetriever.getFileEncryptionProperties(CryptoMetadataRetriever.java:114)
    at org.apache.parquet.crypto.CryptoClassLoader.getFileEncryptionPropertiesOrNull(CryptoClassLoader.java:74)
    at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:405)
    at org.apache.parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:362)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetOutputWriter.<init>(ParquetOutputWriter.scala:37)
    at org.apache.spark.sql.execution.datasources.parquet.ParquetFileFormat$$anon$1.newInstance(ParquetFileFormat.scala:163)
    at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.newOutputWriter(FileFormatDataWriter.scala:120)
    at org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.<init>(FileFormatDataWriter.scala:108)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$.org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask(FileFormatWriter.scala:253)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:170)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:169)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90)
    at org.apache.spark.scheduler.Task.run(Task.scala:121)
    at org.apache.spark.executor.Executor$TaskRunner$$anonfun$11.apply(Executor.scala:440)
    at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1371)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:446)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

触发错误的代码如下:

DataFrameWriter<Row> dfw =
        sparkSession.createDataFrame(javaSparkContext.parallelize(uuids), MyCustomDataClass.class).write();

其中uuids为ArrayList<MyCustomDataClass>类型,需实现将数据以Parquet格式写入Hive表且不触发该错误。

解决方案

该错误核心是Parquet加密组件检测到空字段,而实际场景大概率未启用加密或加密配置缺失,可通过以下方式解决:

  • 显式禁用Parquet加密
    在Spark配置中添加参数强制关闭加密功能,避免加密组件的不必要检查:

    sparkSession.conf().set("spark.sql.parquet.enableEncryption", "false");
    

    或在Spark启动时通过--conf参数设置:

    --conf spark.sql.parquet.enableEncryption=false
    
  • 修复自定义类字段定义
    确保MyCustomDataClass的所有字段均有合法取值,无空值或未初始化情况。若字段允许为空,需标注Spark支持的注解(如@Nullable),让Spark正确识别字段可空性,避免Parquet处理时误判为空字段。

  • 直接写入Hive表
    不要使用通用write()方法,而是指定写入Hive表,让Spark自动适配表的Parquet格式配置:

    sparkSession.createDataFrame(javaSparkContext.parallelize(uuids), MyCustomDataClass.class)
                .write()
                .mode(SaveMode.Append) // 根据需求选择覆盖/追加等模式
                .saveAsTable("database_name.table_name");
    

    该方式会复用Hive表已有Parquet配置,规避手动配置带来的加密相关问题。

  • 检查依赖版本兼容性
    确保Spark、Parquet、Hive的依赖版本匹配。若使用带加密功能的Parquet版本但Spark版本未适配,可能触发此类异常。建议使用官方兼容的依赖组合,比如Spark 3.x搭配Parquet 1.12+版本。

内容的提问来源于stack exchange,提问作者Christopher Settles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:35:45