使用PySpark读取S3上Parquet文件,如何禁用自动类型转换保留原类型?
核心结论:Parquet不存在等效于CSV的inferSchema='false'选项
Parquet是自带完整类型元数据的列式存储格式,Spark读取Parquet文件时,默认会直接加载文件中存储的原始schema,不会像CSV那样自动推断类型(CSV是无元数据的文本格式才需要推断)。你遇到的“字符串转整数”这类自动转换,并非Spark的默认行为,而是由其他因素导致的。
解决方法:确保读取原始类型的步骤
如果遇到数据类型被意外转换的情况,可以按以下方向排查和处理:
关闭Schema合并:当读取多个schema不一致的Parquet文件时,若之前手动开启过
mergeSchema,Spark会尝试合并schema,过程中可能导致类型被自动转换。关闭合并的命令如下:spark.read.option("mergeSchema", "false").parquet("s3://your-bucket/path")关闭后,Spark会严格使用第一个文件的schema,若后续文件schema不兼容则直接报错,避免自动转换。
避免手动指定Schema:如果代码中手动指定了读取的schema(比如
.schema(customSchema)),Spark会用自定义schema覆盖文件的原始元数据,导致类型被强制转换。此时需要移除手动指定的schema配置,让Spark自动读取文件自带的原始schema。检查Parquet文件的写入过程:如果写入Parquet时就错误地设置了schema(比如将字符串数据以整数类型写入),读取时自然会得到转换后的类型。需要检查写入代码,确保写入的schema与原始数据类型一致。
排查Spark版本兼容性:部分旧版本Spark对Parquet的某些类型(如Decimal、Int96日期类型)处理存在差异,可能导致类型解析异常。可以尝试升级Spark版本,或者设置对应类型的解析参数,例如针对Int96日期类型的:
spark.conf.set("spark.sql.parquet.int96RebaseModeInRead", "LEGACY")
内容的提问来源于stack exchange,提问作者Dozel

