Spark SQL解析查詢parquet格式Hive表獲取分區字段和查詢條件


首先說一下,這里解決的問題應用場景:

sparksql處理Hive表數據時,判斷加載的是否是分區表,以及分區表的字段有哪些?再進一步限制查詢分區表必須指定分區?

這里涉及到兩種情況:select SQL查詢和加載Hive表路徑的方式。這里僅就"加載Hive表路徑的方式"解析分區表字段,在處理時出現的一些問題及解決作出詳細說明。

如果大家有類似的需求,筆者建議通過解析Spark SQL logical plan和下面說的這種方式解決方案結合,封裝成一個通用的工具。

問題現象

sparksql加載指定Hive分區表路徑,生成的DataSet沒有分區字段。

如,

sparkSession.read.format("parquet").load(s"${hive_path}"),hive_path為Hive分區表在HDFS上的存儲路徑。

hive_path的幾種指定方式會導致這種情況的發生(test_partition是一個Hive外部分區表,dt是它的分區字段,分區數據有dt為20200101和20200102):

1. hive_path為"/spark/dw/test.db/test_partition/dt=20200101"

2. hive_path為"/spark/dw/test.db/test_partition/*"

因為牽涉到的源碼比較多,這里僅以示例的程序中涉及到的源碼中的class、object和方法,繪制成xmind圖如下,想細心研究的可以參考該圖到spark源碼中進行分析。

問題分析

我這里主要給出幾個源碼段,結合上述xmind圖理解:

 

 

在沒有指定參數basePath的情況下:

1. hive_path為/spark/dw/test.db/test_partition/dt=20200101

sparksql底層處理后得到的basePaths: Set(new Path(“/spark/dw/test.db/test_partition/dt=20200101”))【偽代碼】

leafDirs: Seq(new Path(“/spark/dw/test.db/test_partition/dt=20200101”))【偽代碼】

2. hive_path為/spark/dw/test.db/test_partition/*

sparksql底層處理后得到的basePaths: Set(new Path(“/spark/dw/test.db/test_partition/dt=20200101”),new Path(“/spark/dw/test.db/test_partition/dt=20200102”))【偽代碼】

leafDirs: Seq(new Path(“/spark/dw/test.db/test_partition/dt=20200101”),new Path(“/spark/dw/test.db/test_partition/dt=20200102”))【偽代碼】

這兩種情況導致源碼if(basePaths.contains(currentPath))為true,還沒有解析分區就重置變量finished為true跳出循環,因此最終生成的結果也就沒有分區字段:

 

解決方案(親測有效)

1. 在Spark SQL加載Hive表數據路徑時,指定參數basePath,如

sparkSession.read.option("basePath","/spark/dw/test.db/test_partition")

2. 主要重寫basePaths方法和parsePartition方法中的處理邏輯,同時需要修改其他涉及的代碼。由於涉及需要改寫的代碼比較多,可以封裝成工具

關聯文章:

Spark SQL

Apache Hive

必須掌握的分布式文件存儲系統—HDFS


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM