Azure Databricks高效读取分区JSON至Spark DataFrame问题
解决Azure Databricks读取分区嵌套JSON数据集的问题
针对你遇到的读取失败、需指定Schema但想保留嵌套结构的问题,可通过以下几种实用方案解决:
方案一:先获取样本Schema再批量读取
当Spark无法自动推断复杂嵌套JSON的Schema时,先读取单个分区下的文件生成完整Schema,再用该Schema读取整个上层分区,既保留嵌套结构,又能自动识别分区列:
# 1. 读取一个结构确定的groupNumber目录下的文件,生成完整Schema sample_path = "/abc/runDate=20240130101010/familyNumber=xxx/groupNumber=yyy" sample_df = spark.read.json(sample_path) full_nested_schema = sample_df.schema # 2. 用生成的Schema读取整个runDate层级,Spark会自动识别分区列 final_df = spark.read.schema(full_nested_schema).json("/abc/runDate=20240130101010/")
方案二:调整JSON读取参数强制保留嵌套结构
如果JSON文件结构统一,可通过配置读取参数让Spark正确识别嵌套结构,无需手动指定Schema:
# 根据JSON格式调整参数:如果是每个文件一个完整JSON对象,开启multiLine # 如果是每行一个JSON对象,去掉multiLine参数 final_df = spark.read.option("multiLine", "true") \ .option("inferSchema", "true") \ .json("/abc/runDate=20240130101010/")
注:inferSchema=true会让Spark扫描文件推断完整嵌套Schema,若数据集极大,此方法效率略低于方案一。
方案三:手动读取文本并解析JSON(极端情况)
若自动分区识别失效,可直接读取文件内容为文本,手动解析JSON并提取分区列:
from pyspark.sql.functions import input_file_name, concat_ws, collect_list, from_json, regexp_extract # 1. 读取所有JSON文件为文本行 text_df = spark.read.text("/abc/runDate=20240130101010/**") # 2. 针对多行JSON,按文件合并内容(单行JSON可跳过此步) multi_line_df = text_df.groupBy(input_file_name()).agg(concat_ws("\n", collect_list("value")).alias("json_str")) # 3. 用样本Schema解析JSON字符串 parsed_df = multi_line_df.withColumn("data", from_json("json_str", full_nested_schema)) \ .select("data.*", input_file_name().alias("file_path")) # 4. 从文件路径中手动提取分区列 parsed_df = parsed_df.withColumn("runDate", regexp_extract("file_path", "runDate=(\d+)", 1)) \ .withColumn("familyNumber", regexp_extract("file_path", "familyNumber=(\w+)", 1)) \ .withColumn("groupNumber", regexp_extract("file_path", "groupNumber=(\w+)", 1))
额外注意事项
- 确认Azure容器已正确挂载到Databricks,集群拥有容器的读取权限(如通过SAS Token或服务主体配置);
- 若数据集超大,优先使用方案一,避免全量扫描推断Schema带来的性能损耗。
内容的提问来源于stack exchange,提问作者pramod sahoo
相关产品推荐
相关产品推荐

