首页 > 其他分享 >第05章-自定义函数和JSON数据解析

第05章-自定义函数和JSON数据解析

时间:2023-09-19 22:03:08浏览次数:47  
标签:tmp 自定义 05 object json hive JSON state 解析

目录

5.1 实现自定义UDF 2

5.2 实现自定义UDTF 3

5.3 实现自定义UDAF 4

5.4 解析JSON数据 6

5.4.1 解析OBJECT数据 6

5.4.2 解析ARRAY数据 7

5.4.3 禁止使用get_json_object函数 8

第05章 自定义函数和JSON数据解析

自定义函数简介

有一些sql很难处理的逻辑,我们可以使用自定义函数去处理。比如对一个字符串加密、对字符串解密、解析json,调用外部服务等。

5.1 实现自定义UDF

UDF就是一进一出的函数,类似于Spark SQL中的round(四舍五入)函数。

输入是一行数据的某一个字段,转为某一个值。

先引入jar包

<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>${hive.version}</version>
<scope>provided</scope>
</dependency>

再开发UDF代码,我们在这里实现一个将字符串转为大写的功能

/**
* 将字符串转为大写字符串
*/
@Description(name = "up",value = "_FUNC_(object) - 将字符串转大写字符串")public class Up extends UDF {public String evaluate(Object key) {if(null==key){return null;}return key.toString().toUpperCase();}
}

再编译代码mvn clean package -DskipTests

并将编译后的代码上传到hdfs上

hadoop fs -put /Users/jack/eclipse-workspace/udf/target/udf-1.0-SNAPSHOT.jar /tmp/hive/

启动spark-sql并创建临时UDF函数

create temporary function up as 'udf.Up' using jar 'hdfs:///tmp/hive/udf-1.0-SNAPSHOT.jar';

使用UDF查询数据

spark-sql> select up("aadbbc");

AADBBC

Time taken: 0.074 seconds, Fetched 1 row(s)

项目github地址:

https://github.com/liukunyuan/udf_new.git

5.2 实现自定义UDTF

UDTF就是一进多出的函数,类似于Spark SQL中的split(对字段分割)函数。将输入的一行数据的某一个字段,转为一个数组。

开发UDTF代码,我们在这里实现一个将字符串转为集合对象的功能

@Description(name = "json_array",value = "_FUNC_(array_string) - 将字符串转为集合对象")public class JsonArray extends UDF {public ArrayList<String> evaluate(String jsonString) throws JSONException {if (StringUtils.isBlank(jsonString)) {return null;}
JSONArray extractObject = new JSONArray(jsonString);ArrayList<String> result = new ArrayList<String>();
for (int i = 0; i < extractObject.length(); i++) {
result.add(extractObject.get(i).toString());}return result;}
}

再编译代码mvn clean package -DskipTests

并将编译后的代码上传到hdfs上

hadoop fs -put /Users/jack/eclipse-workspace/udf/target/udf-1.0-SNAPSHOT.jar /tmp/hive/

启动spark-sql并创建临时UDTF函数

create temporary function json_array as 'udtf.JsonArray' using jar 'hdfs:///tmp/hive/udf-1.0-SNAPSHOT.jar';

使用UDTF查询JSON数据

spark-sql> select json_array("[{ \"name\": \"XiaoHong\", \"age\":18}]");

["{"name":"XiaoHong","age":18}"]

Time taken: 0.055 seconds, Fetched 1 row(s)

spark-sql>

5.3 实现自定义UDAF

UDAF就是多进一出的函数,类似于Spark SQL中的count(求条数)函数。将输入的多行数据的某一个值,转为一个值。

开发UDAF代码,我们在这里实现一个求平均数的功能。

参考:org.apache.hadoop.hive.contrib.udaf.example.UDAFExampleAvg



@Description(name = "avg_num",value = "_FUNC_(col) - 计算平均数")public class AvgNum extends UDAF {public static class UDAFAvgState {private long mCount;
private double mSum;}public static class UDAFExampleAvgEvaluator implements UDAFEvaluator {
UDAFAvgState state;
public UDAFExampleAvgEvaluator() {super();state = new UDAFAvgState();init();}public void init() {state.mSum = 0;state.mCount = 0;}/**
* 遍历所有行
*
@param o* @return*/public boolean iterate(Double o) {if (o != null) {state.mSum += o;state.mCount++;}return true;}/**
* 输出部分聚合结果
*
@return*/public UDAFAvgState terminatePartial() {// This is SQL standard - average of zero items should be null.return state.mCount == 0 ? null : state;}/**
* 提前合并部分数据
*
@param o* @return*/public boolean merge(UDAFAvgState o) {if (o != null) {state.mSum += o.mSum;state.mCount += o.mCount;}return true;}/**
* 终止聚合并返回最终结果
*
@return*/public Double terminate() {// This is SQL standard - average of zero items should be null.return state.mCount == 0 ? null : Double.valueOf(state.mSum/ state.mCount);}
}
}

再编译代码mvn clean package -DskipTests

并将编译后的代码上传到hdfs上

hadoop fs -put /Users/jack/eclipse-workspace/udf/target/udf-1.0-SNAPSHOT.jar /tmp/hive/

hadoop fs -put /Users/jack/Desktop/test.csv hdfs:///tmp/hive/csv/

启动spark-sql并创建临时UDAF函数

create table default.csv(data int)

location '/tmp/hive/csv';

create temporary function avg_num as 'udaf.AvgNum' using jar 'hdfs:///tmp/hive/udf-1.0-SNAPSHOT.jar';

使用UDAF查询数据

spark-sql> select avg_num(data) ,avg(data) from default.csv;

93.4 93.4

Time taken: 1.888 seconds, Fetched 1 row(s)

可以发现,我们实现的求平均数和引擎自带的avg功能一致。

5.4 解析JSON数据

在大数据处理中,我们经常会遇到一些json格式的数据,所以我们必须掌握如何在Spark SQL中处理json数据。而json数据分为json object格式和json array格式。而我们将通过如下学习掌握这2种json格式数据的通用解析方法。

5.4.1 解析OBJECT数据

通过lateral view outer json_tuple解析json object类型数据,单次可以解析多个key,性能比get_json_object好。

第05章-自定义函数和JSON数据解析_hive

创建存放json数据的目录

hadoop fs -mkdir hdfs:///tmp/hive/json

将JSON数据上传到hdfs

hadoop fs -put /Users/jack/Desktop/test.json hdfs:///tmp/hive/json/

create table default.test (data string)

location '/tmp/hive/json';

书写sql查询数据里面的所有class

select t2.class

from default.test t

lateral view outer json_tuple(data,'class','cmd') t2 as class,cmd

limit 10;

注意:不要使用get_json_object处理json object数据,如果解析多个字段,会重复解析多次,性能很差。

5.4.2 解析ARRAY数据

通过我们前面编写的自定义函数json_array将字符串转成array类型数据,然后通过LATERAL view explode将array进行行转列。通过这种方式解析json array数据。

书写sql查询第二层的class字段

select t4.cmd_class

from default.test t

lateral view outer json_tuple(data,'class','cmd') t2 as class,cmd

LATERAL view explode(json_array(cmd)) t3 as tmp_object

lateral view outer json_tuple(tmp_object,'class') t4 as cmd_class

limit 10;

5.4.3 禁止使用get_json_object函数

这是我们优化json解析的生产案例:

优化前,解析json需要执行360分钟。优化后,解析json只需要执行24分钟,性能优化了15倍。

这是优化前的sql,有1000个get_json_object解析

select

t1.biz_no,

from_unixtime(cast(t1.date_created/1000 as int),'yyyy-MM-dd') as date_created,

get_json_object(t1.req_data,'$.hfwCredit_cust.casesNum') casesNum,

get_json_object(t1.req_data,'$.hfwCredit_cust.breakFaithNum') breakFaithNum,

get_json_object(t1.req_data,'$.caseInfo.custNo') cust_no,

get_json_object(t1.req_data,'$.caseInfo.adjDate') adjDate

……………………

from hdp_credit.xx t1 where pday='${pday}';

这是优化后的sql,使用lateral view outer json_tuple进行json解析。

select biz_no, pday, date_created, casesNum, breakFaithNum, adjDate, custNo

from (

select t1.biz_no,

pday,

from_unixtime(cast(t1.date_created / 1000 as int), 'yyyy-MM-dd') as date_created, map_array(t1.resp_data, 'dcItem,dcVal') as resp_data_json,

t2.*

t3.*

t4.*

from

(select * from hdp_credit.xx

where pday='20220424' ) t1

lateral view outer json_tuple(t1.req_data,'caseInfo','hfwCredit_cust') t2 as caseInfo,hfwCredit_cust

lateral view outer json_tuple(hfwCredit_cust,'breakFaithNum','casesNum') t3 asbreakFaithNum,casesNum lateral view outer json_tuple(caseInfo,'adjDate','custNo') t4 as adjDate,custNo

)tt

;

来自视频:《Spark SQL性能优化》

链接地址:

https://edu.51cto.com/course/34516.html

标签:tmp,自定义,05,object,json,hive,JSON,state,解析
From: https://blog.51cto.com/u_12539341/7529685

相关文章

  • Python 如何把 String 转换为 Json 对象
    在我们对JSON进行处理的时候,大概率我们会需要把字符串转换为JSON对象后才能进行处理。Python贴心的使用json.loads(employee_string)就可以了。首先需要做的就是导入JSON库。#includejsonlibraryimportjson对现代程序员来说,JSON数据结构基本上是非常常见的数据......
  • 小夜灯CB证书CE证书LVD证书EMC证书FCC证书EN60598-2-12
    小夜灯检测报告找我办理。小夜灯GB7000.212报告,小夜灯IEC60598-2-12报告小夜灯EN60598-2-12报告小夜灯CE证书小夜灯FCC证书小夜灯ROHS证书小夜灯REACH证书小夜灯EN62471报告小夜灯SAA证书小夜灯CB证书小夜灯TUV证书小夜灯COC证书小夜灯LVD证书小夜灯EMC证书小夜灯I......
  • uniapp项目实践总结(十八)自定义多列瀑布流组件
    导语:有时候展示图片等内容,会遇到图片高度不一致的情况,这时候就不能使用等高双列或多列展示了,这时候会用到瀑布流的页面布局,下面就一起探讨一下瀑布流的实现方法。目录准备工作原理分析实战演练案例展示准备工作在pages/index文件夹下面新建一个waterfall.vue的组件;按......
  • 在C#中如何自定义配置上周和本周起始日来查询业务数据?
    作者:西瓜程序猿主页传送门:https://blog.51cto.com/kimiliucn前言在做某个报表管理功能时,有一个需求:需要根据自定义配置的[周起始日]来统计上周、本周的订单数据。在C#中并没有封装的方法根据我们需要来直接获取上一周某天到某天、本周某天到某天,所以需要我们自己封装方法来实现(我们......
  • 05访问控制:如何选取一个合适的数据保护方案?
    身份认证的核心问题是身份管理,因此我们可以采用单点登录的形式,来解决复杂的身份管理问题。常用的单点登录方式包括CAS流程、JWT、OAuth和OpenID。通过身份认证,我们只能够确认用户的身份,而对用户的操作和访问行为的把控,就是授权和审计的任务了。“授权”和“访问控制”其实是同一......
  • Jasper模板使用记录二——JSON文件数据源
    json文件数据源1.新建json文件,并将字段补充完整,示例如下:{ hosp_name:"医院", rows:[{ name:"姓名", age:12, }]}2.新建json数据源,如下:3.新建Jasper文件4.设置数据源,并导入数据源字段至Fields5.通过拖拽Paramter或Field至模板,进行模板设计......
  • Go每日一库之15:gojsonq
    简介在日常工作中,每一名开发者,不管是前端还是后端,都经常使用JSON。JSON是一个很简单的数据交换格式。相比于XML,它灵活、轻巧、使用方便。JSON也是RESTfulAPI推荐的格式。有时,我们只想读取JSON中的某一些字段。如果自己手动解析、一层一层读取,这就变得异常繁琐了。特别是在......
  • 在C#中如何自定义配置上周和本周起始日来查询业务数据?
    作者:西瓜程序猿主页传送门:https://www.cnblogs.com/kimiliucn前言在做某个报表管理功能时,有一个需求:需要根据自定义配置的[周起始日]来统计上周、本周的订单数据。在C#中并没有封装的方法根据我们需要来直接获取上一周某天到某天、本周某天到某天,所以需要我们自己封装方法......
  • arcgis for js4.x自定义Graphic数组创建FeatureLayer添加标注
    varpoint=[{ "geometry":{ "x":116.820688, "y":33.974053, "spatialReference":{ "wkid":4326 } }, "......
  • Java利用Jackson轻松处理JSON序列化与反序列化
    目录1.@JsonProperty2.@JsonFormat3.@JsonIgnore4.@JsonIgnoreProperties5.@JsonInclude6.@JsonTypeInfo和@JsonSubTypes7.@JsonView8.@JsonNaming9.@JsonSerialize和@JsonDeserialize10.@JsonAnyGetter和@JsonAnySetter11.@JsonIdentityInfo总结......