如何通过Azure Databricks查询Azure存储多文件夹下的多个文件
Azure Databricks 查询分层存储Azure诊断日志最优方案
针对你这种按年/月/日/小时/分钟分层存储的多行JSON格式Azure Diagnostics日志,最高效的查询方式是利用路径通配+Spark原生JSON解析能力,不需要遍历全量文件夹,也不需要额外的ETL步骤,直接就能实现跨时间范围的批量查询。
前置准备
- 先完成存储账号访问授权:在Databricks工作区配置对应Blob存储账号的访问权限,推荐用ABFSS协议访问(比旧版WASB协议延迟低30%以上),支持存储密钥、服务主体、托管身份三种授权方式,选你环境里已经在用的即可。
- 确认日志格式:Azure Diagnostics默认输出的是每行一条JSON记录的格式,也就是常说的JSON Lines格式,读取的时候参数不要配错。
方案1:精准路径通配查询(推荐,性能最高)
你的日志路径结构是固定的y=年份/m=月份/d=日期/h=小时/m=分钟/,直接用通配符匹配目标时间范围的路径即可,Spark只会扫描匹配到的文件,不会做全容器遍历,扫描量最小,速度最快。
示例代码(以查询2022年5月23日-24日全天日志为例):
# 替换成你实际的容器名、存储账号名,前缀固定到资源ID那层即可 base_path = "abfss://<你的容器名>@<你的存储账号名>.dfs.core.windows.net/resourceId=/SUBSCRIPTIONS/53TestSubscriptionIDB/RESOURCEGROUPS/AZURE-DEV/PROVIDERS/MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/AZURE-DEV" # 配置要匹配的路径规则,*代表匹配该层级下所有子文件夹和文件 target_path_patterns = [ f"{base_path}/y=2022/m=05/d=23/*/*/*.json", # 匹配23日所有小时、分钟目录下的json日志 f"{base_path}/y=2022/m=05/d=24/*/*/*.json" # 匹配24日所有小时、分钟目录下的json日志 ] # 读取日志,注意multiLine设为false,对应每行一条JSON的格式 log_df = spark.read.option("multiLine", "false").json(target_path_patterns) # 注册临时视图后,就可以直接用DataFrame API或者SQL做查询分析 log_df.createOrReplaceTempView("aks_diag_logs")
注意:如果不需要查全天,比如只查23日13点到24日凌晨1点的日志,直接调整通配规则即可,例如
d=23/h=1[3-9]/*/*.json、d=24/h=00/*/*.json,匹配精度越高,查询速度越快。
方案2:分区自动发现(适合长期高频查询场景)
如果需要长期频繁查询该日志目录,可以开启Spark的分区自动发现能力,把路径里的y、m、d、h、m字段自动识别为分区列,后续查询直接写时间过滤条件即可,Spark会自动做分区裁剪,不需要每次手动拼路径规则。
示例代码:
base_path = "abfss://<你的容器名>@<你的存储账号名>.dfs.core.windows.net/resourceId=/SUBSCRIPTIONS/53TestSubscriptionIDB/RESOURCEGROUPS/AZURE-DEV/PROVIDERS/MICROSOFT.CONTAINERSERVICE/MANAGEDCLUSTERS/AZURE-DEV" # 开启分区发现读取根路径下所有日志 log_df = spark.read.option("multiLine", "false") \ .option("basePath", base_path) \ .json(f"{base_path}/y=*/m=*/d=*/h=*/m=*/*.json") log_df.createOrReplaceTempView("aks_diag_logs") # 直接写SQL过滤时间范围即可,Spark会自动跳过不需要扫描的文件夹 result = spark.sql(""" SELECT timeGenerated, level, message, properties FROM aks_diag_logs WHERE y = 2022 AND m = '05' AND d BETWEEN '23' AND '24' """)
性能优化提示
- 不要直接从容器根目录做全递归读取,全量列文件的耗时会随着日志量上涨线性增加,优先用上面两种带路径裁剪的方式读取,大时间范围查询能节省数分钟的文件枚举时间。
- 读取时如果只需要分析特定字段,不要用
select *,直接在read后指定需要的列,能大幅减少数据拉取量。 - 如果需要反复查询同一个时间范围的日志,可以把读取后的结果写入Delta表做持久化,后续查询速度比直接读原始Blob上的JSON快一个数量级。
内容的提问来源于stack exchange,提问作者ZZZSharePoint
相关产品推荐
相关产品推荐

