背景
 
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日志数据时会比较繁琐。

Hive JSON数据处理的一点探索的更多相关文章

  1. Spark SQL JSON数据处理

    背景   这一篇可以说是“Hive JSON数据处理的一点探索”的兄弟篇.   平台为了加速即席查询的分析效率,在我们的Hadoop集群上安装部署了Spark Server,并且与我们的Hive数据仓 ...

  2. 【多端应用开发系列1.1.1 —— Android:使用新浪API V2】服务器Json数据处理——Json数据概述

    [前白] 一些基础的东西本系列中就不再详述了,争取尽量写些必不可少的技术要点. 由于本系列把Web Service 构建放到了第二部分,Android项目就采用新浪微博API v2作为服务器端. [原 ...

  3. iOS开发——数据解析Swift篇&简单json数据处理

    简单json数据处理 //loadWeather var url = NSURL(string: "http://www.weather.com.cn/adat/sk/101240701.h ...

  4. C++对象的JSON序列化与反序列化探索完结-列表的序列化与反序列化

    在前两篇文章中,我们已经完成对普通对象以及复杂对象嵌套的序列化与反序列化,见如下地址: C++对象的JSON序列化与反序列化探索 C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化 ...

  5. C++对象的JSON序列化与反序列化探索续-复杂对象的序列化与反序列化

    本文是基本上一篇博文进行改进而成,上一篇请见: C++对象的JSON序列化与反序列化探索 此处就不多说了,直接上代码. 1. 序列化基类 #pragma once #include <strin ...

  6. python接口自动化(十九)--Json 数据处理---实战(详解)

    简介 上一篇说了关于json数据处理,是为了断言方便,这篇就带各位小伙伴实战一下.首先捋一下思路,然后根据思路一步一步的去实现和实战,不要一开始就盲目的动手和无头苍蝇一样到处乱撞,撞得头破血流后而放弃 ...

  7. Python 关于Python函数参数传递方式的一点探索

    关于Python函数参数传递方式的一点探索 by:授客 QQ:1033553122 实践代码 #!/usr/bin/env python # -*- coding:utf-8 -*- __author ...

  8. JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法

    Jackson是Spring Boot默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的,没有这种限制.它提供了很 ...

  9. python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)

    简介 有些 post 的请求参数是 json 格式的,这个前面发送post 请求里面提到过,需要导入 json模块处理.现在企业公司一般常见的接口因为json数据容易处理,所以绝大多数返回数据也是 j ...

随机推荐

  1. Visual C++ 打印编程技术-编程基础-获取打印机

    标准方法是用: EnumPrinters() 函数获取 #define PRINTER_ENUM_DEFAULT 0x00000001 #define PRINTER_ENUM_LOCAL 0x000 ...

  2. C++ Dialog Box Command IDs

    #define IDOK 1 #define IDCANCEL 2 #define IDABORT 3 #define IDRETRY 4 #define IDIGNORE 5 #define IDY ...

  3. Visual C++ 打印编程技术-编程基础-映射模式

    映射模式: Visual C++ 中采用的坐标映射方式使得用户图形坐标和输出设别的像素完全一致. eg:当屏幕的像素大小为800X600时,每英寸包含屏幕像素为96,打印机则需要几倍的点数才能达到同样 ...

  4. javax.servlet.ServletException: Servlet execution threw an exception 异常解决之一

    配置JDBC连接的JDBC.properties文件不存在(那天很奇怪配置文件不存在了,我也没有去移动那个文件.诡异呀)也会导致这个异常. 然后就报javax.servlet.ServletExcep ...

  5. xcode编译运行报错纪录(持续更新)

    ---恢复内容开始--- 1. Undefined symbols for architecture i386: "_deflate", referenced from: -[NS ...

  6. 【BZOJ3529】【莫比乌斯反演 + 树状数组】[Sdoi2014]数表

    Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于 ...

  7. CentOS系统Apache服务器优化详解

    1.Apache优化 Apache能够在CentOS系统正常运行.但是,对于访问量稍大的站点,Apache的这些默认配置是无法满足需求的,我们仍需调整Apache的一些参数,使Apache能够在大访问 ...

  8. web前端工程师必须掌握的localStorage(二)

    最近工作太忙了,回来后就很晚了,因为红牛喝太多都不想睡觉了(公司免费给的,好多箱o(╯□╰)o),睡不着就想着逛逛博客园,本人最近忙着做一个仿原生app的singlePage应用,话说最近后台那帮兄弟 ...

  9. onmouseleave与onmouseout区别

    1.onmouseleave.onmouseenter,鼠标进入到指定元素区域内触发事件,不支持冒泡,不包含子元素的区域. 2.onmouseout.onmouseover.鼠标进入指定元素触发事件, ...

  10. DIV+CSS 网页布局之:一列布局

    1.网页布局 布局(layout)即对事物的全面规划和安排,页面布局是对页面的文字.图像或表格进行格式化版式排列.网页布局对改善网站的外观非常重要,又称版式布局,大多数网站会把内容安排到多个列中,就像 ...