背景
 
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. 安装flash 插件scaleform出现错误:Scaleform Launch Panel.Launcher.handleDataLoaderIOError(): Loading XML Failedscaleform

    经排查发现是Scaleform Launcher.swf报的错 (C:\Users\Administrator\AppData\Local\Adobe\Flash CC\zh_CN\Configura ...

  2. std::map的操作:插入、修改、删除和遍历

    using namespace std; std::map<int,int> m_map; 1.添加 for(int i=0;i<10;i++) { m_map.insert(mak ...

  3. 在Windows下用gSoap实现简单加法实例

    实现一个简单的a+b程序,在服务器端写一个程序,里面包含了a+b的函数,然后通过客户端代码向其发送两个数字,在服务器运算得到结果返回给客户端显示出来. 1.在gSoap的官网上下载文件夹,本人的版本是 ...

  4. SQL优化(2)

    建表时候数据库引擎的选择也可以达到优化的效果 InnoDB: 基于磁盘的资源是InnoDB表空间数据文件和它的日志文件,InnoDB 表的大小只受限于操作系统文件的大小,一般为 2GB MyISAM: ...

  5. Graphviz使用简介(中文乱码的问题)

    Graphviz使用简介 graphviz是基于dot语言的绘图工具,可以画有向图.无向图.关系图.目录图.流程图等.具体作用可见它的官方网站 一些参考的网址: http://www.open-ope ...

  6. [CUDA] ubuntu14.04+cuda7.5下安装cudnn7.0

    cuda:7.5 cudnn:cudnn-7.0-linux-x64-v4.0-prod.tgz cudnn样例:cuDNN v4 Code Samples 1. 解压 tar -zxvf cudnn ...

  7. oracle创建表(并且实现ID自增)

    CREATE TABLE STUDENT ( ID INT NOT NULL, NAME VARCHAR2(4000) NOT NULL, PRIMARY KEY(ID) ) TABLESPACE M ...

  8. [转] 使用maven运行java main的三种方式

    原文地址: http://blog.csdn.net/qbg19881206/article/details/19850857?utm_source=tuicool&utm_medium=re ...

  9. Oracle安装时忘记解锁scott用户的解决方案

    最近笔者开始学习Oracle,对于笔者同学安装过程出现各种问题而导致重做系统表示默哀. (1)问题1:64位操作系统安装完以后选择java.exe文件后.sqldeveloper闪退,原因是64位操作 ...

  10. lnmp安装--php与nginx结合

    软件环境: linux:centos5. nginx:.tar.gz php:.tar.gz lnmp与lamp的区别? lnmp(linux+nginx+mysql+php)的提法相对于lamp(l ...