PySpark读取Parquet文件指定Schema后返回NULL值问题求助
首先要明确一个核心点:Parquet是自带Schema元数据的列存储格式,和CSV这种纯文本格式逻辑完全不同。你遇到的全NULL问题,本质是手动指定的Schema和文件实际的Schema不匹配,导致Spark无法正确映射数据。下面一步步帮你排查解决:
第一步:先确认Parquet文件的实际Schema
在调整自定义Schema之前,必须先搞清楚文件本身的列名和数据类型,这是解决问题的关键。你可以用两种方式查看:
方法1:用Spark自动读取并查看Schema
# 不指定Schema,让Spark自动加载文件自带的元数据 temp_df = spark.read.parquet("data/locations.parquet") # 打印完整的Schema结构 temp_df.printSchema() # 预览前5行数据,确认列名和内容对应关系 temp_df.show(5)
方法2:用已成功读取的Pandas数据查看结构
既然你已经能用Pandas读取文件,直接查看列名和数据类型:
great = pd.read_parquet('data/locations.parquet', engine='auto') # 输出列名 print("文件实际列名:", great.columns.tolist()) # 输出各列数据类型 print("列数据类型:\n", great.dtypes)
对比你定义的location_schema,你会发现问题所在——要么是列名不匹配(比如文件里是location_id而不是loc_id),要么是数据类型不匹配(比如loc_id实际是字符串类型而非整数)。
第二步:修正你的读取代码
1. 删除不必要的CSV参数
你代码里加了.options(header='false'),这是专门给CSV读取用的参数,Parquet完全不需要,反而可能干扰读取逻辑,直接删掉即可。
2. 调整自定义Schema匹配实际文件
根据第一步查到的真实Schema,修改你的location_schema。比如如果实际列名是location_id(整数)和description(字符串),修正后的Schema应该是:
from pyspark.sql.types import StructType, StructField, IntegerType, StringType location_schema = StructType([ StructField("location_id", IntegerType(), nullable=True), StructField("description", StringType(), nullable=True) ])
3. 使用更稳定的临时表注册API
registerTempTable是Spark 1.x的旧API,推荐使用createOrReplaceTempView(Spark 2.x及以上版本支持),功能更稳定且兼容性更好。
修正后的完整代码
from pyspark.sql.types import StructType, StructField, IntegerType, StringType # 匹配文件实际Schema的自定义Schema location_schema = StructType([ StructField("loc_id", IntegerType(), nullable=True), StructField("descr", StringType(), nullable=True) ]) # 读取Parquet文件,去掉多余的header参数 location_df = spark.read.format('parquet') \ .schema(location_schema) \ .load("data/locations.parquet") # 注册临时视图 location_df.createOrReplaceTempView("location") # 执行查询并查看结果 query = spark.sql("select * from location") query.show(100)
为什么会出现这种情况?
- Parquet的Schema是嵌入在文件元数据中的,当你手动指定Schema时,Spark会严格按照你给出的列名、类型、顺序去匹配文件中的数据。一旦不匹配,就会返回NULL(要么找不到对应列,要么类型转换失败)。
- Pandas的
read_parquet会自动读取文件自带的Schema,所以不需要手动指定就能正确解析数据。 - 你读取CSV时正常,是因为CSV没有自带Schema,Spark会根据你指定的Schema或自动推断的规则解析纯文本,逻辑和Parquet完全不同。
额外提示
如果你的Parquet文件是从CSV转换而来的,要确认转换过程中是否正确保留了Schema(比如转换时有没有把表头作为列名,而不是把第一行数据当成列名)。如果转换环节出了问题,也会导致后续读取异常。
内容的提问来源于stack exchange,提问作者Nissus

