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日志數據時會比較繁瑣。


免責聲明!

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



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