hive创建和使用json格式的分区外表

引子

记录这篇博文是因为是因为有客户反馈过来一个hive问题:
对一个hive中的json数据外表执行 select * from table_name limit 1;报错:RuntimeException org.apache.hadoop.hive.ql.metadata.HiveException: Failed with exception nulljava.lang.NullPointerException

就先用自己的集群做了测试,发现是OK,最后去客户的集群操作同样的测试会报错,最后发现客户的集群hive版本很老1.1的,而我在hive1.2.1, hive 2.3.3上测试都是ok, 最后去社区去查了下,发现是hive 1.1版本的一个bug, 在1.2.0版本已经修复,最后推荐客户升级版本解决问题。

1.1.0修复的patch在这里,问题描述大概是, 如果对定义了分区的hive表做查询但不包含map/reduce任务但话,会报错。除了历史原因,应该没多少会在生产中用这个版本了。

这里记录下测试创建json类型的带分区hive外表的操作过程:(在hive1.2.1, hive2.3.3两个版本下进行过测试)

测试过程

  • 创建外表
1
2
3
4
5
6
7
8
9
hive> 
CREATE EXTERNAl TABLE test_json_dt(id BIGINT,text STRING) PARTITIONED BY (
`dt` string) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' STORED AS TEXTFILE LOCATION
'hdfs://Ucluster/tmp/test_json/';

#这里也可以直接写hdfs path的决定路径/tmp/test_json/
# 这里是使用 hcatalog的json包,如果是别的json包,可以使用add jar的方式加载进来
# hive 1.2.1我测试,使用的是org.apache.hadoop.hive.contrib.serde2.JsonSerde, jar目录在/home/hadoop/hive/lib/hive-json-serde.jar. 如果使用org.apache.hive.hcatalog.data.JsonSerD,则 add jar /home/hadoop/hive/hcatalog/share/hcatalog/hive-hcatalog-core-1.2.1.jar
# hive 2.3.3我测试,使用的是org.apache.hive.hcatalog.data.JsonSerDe,jar目录在/home/hadoop/hive/hcatalog/share/hcatalog/hive-hcatalog-core-2.3.3.jar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 之后show create查看完整的创建语句如下
hive> show create table test_json_dt;
OK
CREATE EXTERNAL TABLE `test_json_dt`(
`id` bigint COMMENT 'from deserializer',
`text` string COMMENT 'from deserializer')
PARTITIONED BY (
`dt` string)
ROW FORMAT SERDE
'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://Ucluster/tmp/test_json'
TBLPROPERTIES (
'transient_lastDdlTime'='1572089495')
  • 创建测试文件,并上传到分区表hdfs对应目录
1
2
3
4
5
shell>
echo '{"id":1234544353,"text":"test_hive_json"}' > test.json

hadoop fs -mkdir -p /tmp/test_json/dt=2019-11
hdfs dfs -put test.json /tmp/test_json/dt=2019-11/
  • 修复表分区元信息,并测试
hive>
show partitions test_json_dt;
msck repair table test_json_dt;
show partitions test_json_dt;
#上面两步也可以不做,通过load 将本地数据导入到hive表对应分区下:
#load data local inpath '/home/hadoop/test.json' overwrite into table test_json_dt partition (dt='2019-06-10');


select * from test_json_dt;
select * from test_json_dt;