验证 parquet 文件中的 NULL 值

Posted

技术标签:

【中文标题】验证 parquet 文件中的 NULL 值【英文标题】:Validate NULL values from parquet files 【发布时间】:2020-09-25 10:48:03 【问题描述】:

我正在从第三方读取镶木地板文件。似乎 parquet 总是将文件的架构转换为可为空的列,无论它们是如何编写的。

读取这些文件时,我想拒绝在特定列中包含 NULL 值的文件。使用 csv 或 json 你可以:

schema = StructType([StructField("id", IntegerType(), False), StructField("col1", IntegerType(), False)])
df = spark.read.format("csv").schema(schema).option("mode", "FAILFAST").load(myPath)

如果负载在col1 中包含NULL,则会被拒绝。如果您在 Parquet 中尝试这样做,它将被接受。

我可以对 Null 值的列进行过滤或计数并引发错误 - 从性能立场来看,这很糟糕,因为我将在工作中获得额外的阶段。它还将拒绝完整的数据帧和所有文件(是的,CSV 路由也这样做)。

是否对读取的文件强制执行验证?

如果有帮助,我正在使用版本 Spark 3。

用例子编辑:

from pyspark.sql.types import *
schema = StructType([
  StructField("Id", IntegerType(), False),
  StructField("col1", IntegerType(), True)
])
df = spark.createDataFrame([(1,1),(2, None)], schema)
df.write.format("parquet").mode("overwrite").save("/tmp/parquetValidation/")
df2 = spark.read.format("parquet").load("/tmp/parquetValidation/")
df2.printSchema()

返回

|-- Id: integer (nullable = true) 
|-- col1: integer (nullable = true)

使用阻止空值的架构重新读取文件:

schema = StructType([
  StructField("Id", IntegerType(), False),
  StructField("col1", IntegerType(), False)
])
df3 = spark.read.format("parquet").schema(schema).option("mode", "FAILFAST").load("/tmp/parquetValidation/")
df3.printSchema()

返回:

|-- Id: integer (nullable = true) 
|-- col1: integer (nullable = true)

即未应用架构。

【问题讨论】:

这可以帮助您理解问题。 github.com/apache/spark/pull/17293 .. 甚至还有一种解决方法 【参考方案1】:

感谢 cmets 中的@Sasa 提出问题。

from pyspark.sql import DataFrame

schema = StructType([
  StructField("Id", IntegerType(), False),
  StructField("col1", IntegerType(), False)
])

df_junk = spark.read.format("parquet").schema(schema).load("/tmp/parquetValidation/")

new_java_schema = spark._jvm.org.apache.spark.sql.types.DataType.fromJson(schema.json())
java_rdd = df_junk._jdf.toJavaRDD()
new_jdf = spark._jsparkSession.createDataFrame(java_rdd, new_java_schema)
df_validate = DataFrame(new_jdf, df.sql_ctx)

df_validate.printSchema()

返回

|-- Id: integer (nullable = false)
|-- col1: integer (nullable = false)

运行一个动作会导致:

java.lang.RuntimeException: The 1th field 'col1' of input row cannot be null.

放到 java rdd 上不太好 - 但它可以工作

【讨论】:

以上是关于验证 parquet 文件中的 NULL 值的主要内容,如果未能解决你的问题,请参考以下文章

使用Spark读写Parquet文件验证Parquet自带表头的性质及NULL值来源Java

使用Spark读写Parquet文件验证Parquet自带表头的性质及NULL值来源Java

Parquet文件结构笔记

BigQuery 加载镶木地板错误 - Parquet 中的字段 INT32 与架构中的 double 类型不兼容

使用 Impala 在 HDFS 中查询 Parquet 文件

为 impala 表无缝覆盖底层 parquet 数据