【hive】hive加載json數據和解析json(二)

超久超久沒寫博客了,近來的都是比較雜的臨時活,大家都在喊他的活很急,最要緊,挺令我心煩的,不過有活總比沒活做好吧!

言歸正傳,本文講的是hive解析json格式的數據

 

最近處理了這麼一份數據,json格式的,其實我之前寫了一篇博客:

 

hive加載json數據和解析json(一):https://blog.csdn.net/lsr40/article/details/79399166

 

前言:

上一篇博客雖說介紹了兩種手段處理json

方法一:通過Serde直接加載json

方法二:通過hive內置的函數從字符串總提取json中的value

不過還是相對着重的介紹了get_json_object()和json_tuple()這兩個內置函數,對Serde的使用只是一筆帶過,這次我在做json加載的時候採用了第一種方式(serde加載json)

數據格式如下:

{
	"key1": "xxxx",
	"key2": "XXXX",
	"map1": {
		"M-a": "ma",
		"M-b": "mb",
		"M-c": "mc"
	},
	"last": "last1"
}

提出問題:

解釋下看到數據後我的想法:

1、是否需要額外添加jar包,如何添加?

2、其他的數據都是string類型,map1字段需要是Map或者Struts類型

3、map1中,M-a,M-b,這種不規整的字段名稱,是否可以映射成其他名稱,比如變成m_a,m_b這樣

4、json數據中沒有日期的字段,需要自己生成一個日期字段。

 

解決方法:

問題1的解決:

1、需要添加額外JsonSerde的jar包,可以使用apache有自帶的JsonSerde(上一篇文章中有說),也可以使用另一個功能更加強大的JsonSerde(如果json格式比較複雜,推薦使用後者)

http://www.congiu.net/hive-json-serde/1.3.7/cdh5/json-serde-1.3.7-jar-with-dependencies.jar

2、要添加兩個地方

第一:本地的hive客戶端

在客戶端的hive的lib裏面添加,讓hive啓動的時候能夠直接加載,或者每次手動執行add jar命令

第二:向集羣添加這個jar,放到$HADOOP_HOME/share/hadoop/mapreduce/對應的路徑下

可以參考:http://www.voidcn.com/article/p-dewklslz-bhu.html

必須兩步都做好,否則會有各種各樣的類找不到的報錯

例如:

Task with the most failures(4): 
-----
Task ID:
  task_1559639870610_13878_m_000000

URL:
  http://master節點:8088/taskdetails.jsp?jobid=job_1559639870610_13878&tipid=task_1559639870610_13878_m_000000
-----
Diagnostic Messages for this Task:
Error: java.lang.RuntimeException: Error in configuring object
	at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:109)
	at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:75)
	at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:133)
	at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:455)
	at org.apache.hadoop.mapred.MapTask.run(MapTask.java:343)
	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1924)
	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:106)
	... 9 more
Caused by: java.lang.RuntimeException: Error in configuring object
	at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:109)
	at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:75)
	at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:133)
	at org.apache.hadoop.mapred.MapRunner.configure(MapRunner.java:38)
	... 14 more
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.hadoop.util.ReflectionUtils.setJobConf(ReflectionUtils.java:106)
	... 17 more
Caused by: java.lang.RuntimeException: Map operator initialization failed
	at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.configure(ExecMapper.java:147)
	... 22 more
Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassNotFoundException: Class org.openx.data.jsonserde.JsonSerDe not found
	at org.apache.hadoop.hive.ql.exec.MapOperator.getConvertedOI(MapOperator.java:323)
	at org.apache.hadoop.hive.ql.exec.MapOperator.setChildren(MapOperator.java:333)
	at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.configure(ExecMapper.java:116)
	... 22 more
Caused by: java.lang.ClassNotFoundException: Class org.openx.data.jsonserde.JsonSerDe not found
	at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2255)
	at org.apache.hadoop.hive.ql.plan.PartitionDesc.getDeserializer(PartitionDesc.java:137)
	at org.apache.hadoop.hive.ql.exec.MapOperator.getConvertedOI(MapOperator.java:297)
	... 24 more

 

問題2,3的解決:

問題3只有用推薦的jar包才能解決!

創建表如下:

--先添加剛剛下載到的jar包,然後再創建表
add jar /opt/json-serde-1.3.7-jar-with-dependencies.jar;
create table json_test( 
`key1` string,
`key2` string,
`map1` struct
<
`m_a`:string,
`m_b`:string,
`m_c`:string> ,
`last` string)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties
(
"mapping.m_a" = "M-a",
"mapping.m_b" = "M-b",
"mapping.m_c" = "M-c"
)
STORED AS TEXTFILE;

--其實map1那個字段大家也可以創建成Map<String,String>使用的時候和Strunct有所區別
--一個是map1[m_a],一個是map1.m_a

 

問題4的解決:

問題4是一個很麻煩的問題!

我是這麼做的,新增了一個pt_days的日期分區字段

add jar /opt/json-serde-1.3.7-jar-with-dependencies.jar;
create table json_test( 
`key1` string,
`key2` string,
`map1` struct
<
`m_a`:string,
`m_b`:string,
`m_c`:string> ,
`last` string)
PARTITIONED BY ( 
 `pt_days` string)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties
(
"mapping.m_a" = "M-a",
"mapping.m_b" = "M-b",
"mapping.m_c" = "M-c"
)
STORED AS TEXTFILE;

當我如上建表之後

我執行: load data local inpath 'json文件塊' into json_test partition (pt_days=20191001);

加載數據正常,但是查詢數據的時候直接報空指針的錯:

Failed with exception nulljava.lang.NullPointerException

我估計是Serde解析json數據的時候,找不到pt_days字段,所以報錯了,因爲需求比較急,我也沒有太多的時候認真研究如何解決這個報錯,因此我取了一個折中的方法。

創建一張格式爲orc的有分區的最終表,然後爲每一天數據創建一張臨時表(表名爲:xxxx_數據日期),把當天的數據錄到各自的臨時表中,錄完之後,把該臨時表的數據往最終表裏去導入(導入完成刪除臨時表),這時候添加上時間的字段,而且因爲數據格式變爲orc,既可以節省空間,又可以加快查詢!

 

如果大家有更好的方法,歡迎留言~

好,菜雞一隻,幹活去了溜了溜了!

 

apache的json解析類和我推薦的那個json解析類具體有什麼區別,大家可以百度下,或者看如下的文章:

0659-6.2.0-Hive處理JSON格式數據:https://cloud.tencent.com/developer/article/1451308(作者:Fayson)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章