Hive JSON數據處理的一點探索

背景
 
JSON是一種輕量級的數據格式,結構靈活,支持嵌套,很是易於人的閱讀和編寫,並且主流的編程語言都提供相應的框架或類庫支持與JSON數據的交互,所以大量的系統使用JSON做爲日誌存儲格式。
 
使用Hive分析數據(均指文本)以前,首先須要爲待分析的數據創建一張數據表,而後纔可使用Hive SQL分析這張數據表的數據。這就涉及到咱們如何把一行文本數據映射爲數據表的列,常規的方式有兩種:
 
(1)分隔符
 
 
(2)正則表達式
 
 
可是Hive自己並無針對JSON數據的解析提供原生的支持方式,僅提供了兩個內建函數:get_json_object和json_tuple,用於解析某一列的JSON數據。究其緣由主要是JSON格式的數據太過靈活,尤爲是存在普通數據與JSON數據結合使用、多層嵌套、JSON對象和JSON數組對象結合使用的場景下,常規的數據解析方式變得捉襟見肘。這也是本文探討的重點所在。
 
方案
 
1. 普通數據與JSON數據結合使用,其中JSON數據不存在多層嵌套、JSON對象和JSON數組對象結合使用的狀況;
 
 
能夠認爲上述數據以「&_」分隔,data部分數據格式爲JSON,針對此狀況,咱們選用正則的方式爲其創建數據表,以下:
 
 
驗證數據表解析數據是否正確,
 
 
可見三行數據都正確的被解析,可是咱們沒有辦法直接將「data」的slice_id、status映射爲列,咱們只能經過get_json_object或json_tuple間接的分析數據。
 
由於get_json_object在解析多列數據的場景下存在性能問題,詳情可參考 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-json_tuple,所以這裏咱們僅討論json_tuple。
 
實際是咱們想要的效果無非是將「data」部分的數據也映射爲列,注意到「data」部分的數據所有爲key/value的簡單非嵌套形式,所以咱們能夠這麼作:
 
 
經過Lateral View( https://cwiki.apache.org/confluence/display/Hive/LanguageManual+LateralView)的方式咱們藉助json_tuple的方式獲得了所有的數據列。很顯然若是讓咱們的用戶每次分析數據時都要面對如此複雜的SQL語句編寫,這樣的方式是很不友好的,能夠經過建立視圖的方式將這個過程隱藏。
 
 
視圖mytable_view幫助咱們隱藏了JSON數據與數據列的映射過程,用戶分析數據時僅僅須要操縱一個標準列格式的數據視圖便可。
 
2. JSON數組對象;
 
get_json_object和json_tuple僅僅可以處理JSON對象,而沒有辦法處理JSON數組對象,若是咱們須要解析的是下述的數據:
 
 
Hive內建的功能是沒有辦法支持這樣的數據解析的,所以咱們須要本身擴展。
 
json_tuple可以處理普通的JSON對象,所以咱們要作的只是擴展出一個json_array,能夠將JSON數組對象轉換爲一個JSON對象數組便可。
 
注意:這裏討論的JSON對象、JSON數組對象、JSON對象數組元素均爲JSON字符串。
 
2.1 建立json_array
 
擴展UDF須要繼承GenericUDF,通常狀況下須要重寫兩個方法:initialize、evaluate。
 
initialize核心邏輯以下:
 
(1)參數個數是否爲1,這個參數即爲JSON數組對象的字符串;
(2)定義參數的轉換器,用於後期獲取參數值;
(3)定義UDF返回結果類型:字符串數組;
 
 
evaluate核心邏輯以下:
 
(1)判斷參數個數是否爲1,參數值是否爲空,若是參數合法,則獲取傳入的JSON數組對象字符串jsonArrayStr;
 
 
(2)若是jsonArrayStr爲空字符串,則返回null,不然繼續下一步;
(3)使用Gson解析jsonArrayStr,若是解析失敗,返回null;若是解析成功,須要做出以下判斷:
     a. 若是是JSON數組對象,則繼續下一步;
     b. 若是不是JSON數組對象,則返回null;
(4)將JSON數組對象的各個「元素」的字符串形式存入result並返回(須要注意不一樣的「元素」類型獲取字符串的方式不一樣,此處咱們忽略null)。
 
 
咱們將該類的class文件以及Gson打包爲一個獨立的jar,存入HDFS,而後經過Hive建立Permanent Function,以下:
 
這樣咱們就能夠開始在Hive SQL中使用函數json_array。
 
2.2 使用json_array
 
(1)創建數據表;
 
由於日誌數據爲JSON數組字符串,因此咱們創建的數據表只能爲一列,以下:
 
 
 
(2)使用json_array映射列;
 
每個JSON數組對象包含兩個JSON對象(能夠數目不同),每個JSON對象包含以下屬性:ts、id、log、ip,咱們首先映射這些列,以下:
 
 
第一個Lateral View將JSON數組對象(字符串)轉換爲JSON對象數組(字符串),並經過explode將其轉換爲一個個JSON對象(字符串);
第二個Lateral View將JSON對象(字符串)「映射」爲數據列。
 
咱們還能夠更進一步,利用一樣的方法將「ip」列進行分解,以下:
 
 
咱們還能夠經過前面講述過的建立視圖的方法將上述映射過程隱藏,在此再也不贅述。
 
總結
 
經過Hive內建函數json_tuple以及咱們本身擴展的json_array,二者相互組合能夠很是靈活的完成JSON數據的「映射」,而且能夠經過建立視圖的方式將「映射」過程隱藏。
 
同時咱們也須要注意到,JSON自己是一種很是靈活的數據格式,但實際應用中也不能濫用,如:避免多層嵌套、數據結構不統一等,不然使用Hive分析JSON日誌數據時會比較繁瑣。
相關文章
相關標籤/搜索