Hive复杂日志数据类型的存储与解析

一、基础概览

1.问题背景

  • 实际工作中会遇到很多复杂数据类型,尤其是离线日志中的嵌套json,本文列举几种常见的复杂格式,同时给出存储和解析方法。

2.复杂类型

  • ARRAYARRAY类型是由一系列相同数据类型的元素组成,这些元素可以通过下标来访问。比如有一个ARRAY类型的变量fruits,它是由[‘apple’,‘orange’,‘mango’]组成,那么我们可以通过fruits[1]来访问元素orange,因为ARRAY类型的下标是从0开始的;
  • MAPMAP包含key->value键值对,可以通过key来访问元素。比如”userlist”是一个map类型,其中username是key,password是value;那么我们可以通过userlist[‘username’]来得到这个用户对应的password;
  • STRUCTSTRUCT可以包含不同数据类型的元素。这些元素可以通过”点语法”的方式来得到所需要的元素,比如user是一个STRUCT类型,那么可以通过user.address得到这个用户的地址。

二、场景一

1.日志格式

给出两条日志数据如下,日志本身是一个json,其中event_values又嵌套了一层json。

{
	"user_id":"1",
	"event_name":"people",
	"event_values":
		"{
			"search_word":"hui",
			"search_res":[192061100,819430495],
			"with_result":true
		}",
	"client_timestamp":1500762196
}

{
	"user_id":"2",
	"event_name":"company",
	"event_values":
		"{
			"search_word":"doug",
			"search_res":[81943049,5192025160,85303900],
			"with_result":true
		}",
	"client_timestamp":1500818667
}

2.Hive存储

日志数据接入数仓,一般先存放在ods层,这种比较简单的json数据可以直接存储String类型,建表语句:

CREATE EXTERNAL TABLE `ods_user_info`(	 	
  `user_id` string, 	
  `event_name` string, 	
  `event_values` string, 	
  `client_timestamp` bigint)	
PARTITIONED BY ( 	
  `dt` string)	
ROW FORMAT SERDE 	
  'org.openx.data.jsonserde.JsonSerDe' 	
WITH SERDEPROPERTIES ( 	
  'ignore.malformed.json'='true') 

3.Hive解析

在dwd层会对数据解析,尽可能将复杂字段解析为单个字段,sql如下:

select
	user_id,
	event_name,
	get_json_object(event_values,'$.search_word') as search_word,
    get_json_object(event_values,'$.search_res') as search_res,
    get_json_object(event_values,'$.with_result') as search_res,
	client_timestamp
from ods_user_info;

三、场景二

1.数据准备

给出三条日志数据如下,日志本身是一个json。
重点关注字段"es",它有两种形式: 
	1.单个的list[],里面只有一个json 
	2.嵌套的list[],里面有多个json形成的list(有时候客户端会将打点堆在一起上传) 

{
	"uid":"",
	"t":"1500686183691",
	"p":"PC",
	"es":
		[
			{"en":"version_click","et":"1500686183691"}
		]
}

{
	"es":
		[
			{"en":"menu_click","et":1500767102440}
		]
}

{
    "es":
        [
            {"en":"searchbox_click","et":1500880463517},
            {"en":"show_click","et":1500880463532},
            {"en":"cancel_click","et":1500880477063},
            {"en":"gateway_click","et":1500880568980},
            {"en":"earch_click","et":1500880707281},
            {"en":"trueinc_splash_show","et":1500885445439}      
         ]
}

2.Hive存储

简单字段可以用string或者其他简单类型,但是es如果也是用String,后面是很难的取出来的。所以根据es的格式,使用 array<Struct>类型。建表语句:

CREATE EXTERNAL TABLE `ods_client_event`(	
  `uid` string , 	
  `t` string , 	
  `p` string , 		
  `es` array<struct<en:string,et:string>>)	
PARTITIONED BY ( 	
  `dt` string)	
ROW FORMAT SERDE 	
  'org.openx.data.jsonserde.JsonSerDe' 	
WITH SERDEPROPERTIES ( 	
  'ignore.malformed.json'='true')

3.Hive解析

array<Struct>类型的数据可以使用explode函数炸开,sql如下:

select
	uid,
	t,
	p,
	e.en  as en,
	e.et  as et
from ods_clint_event
lateral view explode(es)  tmp as e
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页