hive作为一个sql查询引擎,自带了一些基本的函数,比如count(计数),sum(求和),有时候这些基本函数满足不了我们的需求,这时候就要写hive hdf(user defined funation),又叫用户自定义函数。

UDF 创建与使用步骤

  • 继承org.apache.hadoop.hive.ql.exec.UDF类,实现evaluate方法;
  • jar包上传到集群,通过create temporary function创建临时函数,不加temporary就创建了一个永久函数;
  • 通过select 语句使用;

例一

下面是一个判断hive表字段是否包含’100’这个子串的简单udf:

package com.js.dataclean.hive.udf.hm2

import org.apache.hadoop.hive.ql.exec.UDF;

public class IsContains100 extends UDF{

	public String evaluate(String s){

        if(s == null || s.length() == 0){
return "0";
} return s.contains("100") ? "1" : "0";
}
}

使用maven将其打包,进入hive cli,输入命令:

add jar /home/hadoop/codejar/flash_format.jar;
create temporary function isContains100 as 'com.js.dataclean.hive.udf.hm2.IsContains100';

创建完临时函数,即可使用这个函数了:

select isContains100('abc100def') from table limit 1;
1

例二

通过读取mysql数据库中的规则,为hive中的workflow返回对应的,类型:

type workflow
a 1
a 2
b 11
b 22
b 33

需求:我们希望,将hive的workflow字段取值为,1,2的变为类型(type)a,取值为11,22,33的全部变为b,就是归类的意思。

这个udf可以这么实现:

package com.js.dataclean.hive.udf.hm2.workflow;

import org.apache.hadoop.hive.ql.exec.UDF;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* @ Author: keguang
* @ Date: 2018/12/13 16:24
* @ version: v1.0.0
* @ description:
*/
public class GetWorkflow extends UDF{ private static final String host = "0.0.0.0";
private static final String port = "3306";
private static final String database = "root";
private static final String userName = "root";
private static final String password = "123456";
private static String url = "";
private static final String driver = "com.mysql.jdbc.Driver";
private static Connection conn = null;
private static Map<String, List<String>> workflowType = null; static {
url = "jdbc:mysql://" + host + ":" + port + "/" + database;
try {
// Class.forName(driver);
conn = DriverManager.getConnection(url, userName, password);
workflowType = getWorkflowType(conn);
} catch (Exception e) {
e.printStackTrace();
} } private static Map<String, List<String>> getWorkflowType(Connection conn){
Map<String, List<String>> workflowType = new HashMap<>();
String sql = "select * from flash_player_workflow";
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()){
String workflow = rs.getString("workflow");
String type = rs.getString("flag"); List<String> workflows = workflowType.get(type);
if(workflows == null){
workflows = new ArrayList<>();
}
workflows.add(workflow);
workflowType.put(type, workflows);
}
} catch (SQLException e) {
e.printStackTrace();
}finally { // 关闭链接
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return workflowType; } public String evaluate(String s){
assert workflowType != null; for(String type:workflowType.keySet()){
List<String> workflows = workflowType.get(type);
if(workflows.contains(s)){
return type;
}
} return s;
} }

打好jar包,创建函数: workflow2type(省略),然后使用:

select workflow2type(workflow) from table;

a
a
b
b
b

这样就把很多取值归为几个大类了。

查看hive function的用法

查month 相关的函数

show functions like '*month*';

查看 add_months 函数的用法

desc function add_months;

查看 add_months 函数的详细说明并举例

desc function extended add_months;

hive 中的 UDAF

可以看出,udf就是一个输入一个输出,输入一个性别,返回’男’或者’女’,如果我们想实现select date,count(1) from table,统计每天的流量呢?这就是一个分组统计,显然是多个输入,一个输出,这时候udf已经不能满足我们的需要,就需要写udaf,user defined aggregare function(用户自定义聚合函数)。

这里写一个字符串连接函数,相当于concat的功能,将多行输入,合并为一个字符串,当然了hive中有字符串连接函数,这里是举例说明UDAF的用法:

package com.js.dataclean.hive.udaf.hm2;

import com.js.dataclean.utils.StringUtil;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator; /**
* 实现字符串连接聚合的UDAF
* @version v1.0.0
* @Author:keguang
* @Date:2018/10/22 14:36
*/
public class MutiStringConcat extends UDAF{
public static class SumState{
private String sumStr;
} public static class SumEvaluator implements UDAFEvaluator{
SumState sumState; public SumEvaluator(){
super();
sumState = new SumState();
init();
} @Override
public void init() {
sumState.sumStr = "";
} /**
* 来了一行数据
* @param s
* @return
*/
public boolean iterate(String s){
if(!StringUtil.isNull(s)){
sumState.sumStr += s;
}
return true;
} /**
* 状态传递
* @return
*/
public SumState terminatePartial() {
return sumState;
} /**
* 子任务合并
* @param state
* @return
*/
public boolean merge(SumState state){
if(state != null){
sumState.sumStr += state.sumStr;
}
return true;
} /**
* 返回最终结果
* @return
*/
public String terminate(){
return sumState.sumStr;
}
}
}

用法,与udf一样,还是需要打包并且到hive cli中注册使用。

关于UDAF开发注意点:

  • 需要import org.apache.hadoop.hive.ql.exec.UDAF以及org.apache.hadoop.hive.ql.exec.UDAFEvaluator,这两个包都是必须的
  • 函数类需要继承UDAF类,内部类Evaluator实现UDAFEvaluator接口
  • Evaluator需要实现 init、iterate、terminatePartial、merge、terminate这几个函数
    • init函数类似于构造函数,用于UDAF的初始化
    • iterate接收传入的参数,并进行内部的轮转。其返回类型为boolean
    • terminatePartial无参数,其为iterate函数轮转结束后,返回乱转数据,iterate和terminatePartial类似于hadoop的Combiner
    • merge接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean
    • terminate返回最终的聚集函数结果

临时与永久函数

Hive自定义函数分为临时与永久函数,顾名思义,分别是临时使用和永久有效使用的意思。

临时函数

临时函数,关闭会话就结束了生命周期,下次要想使用,需要重新注册。

add jar /path/xx.jar(存储在本地磁盘)

// 临时注册UDF函数(hive会话生效)
create temporary function 函数名 as '包名.类名';

删除临时函数:

  • drop temporary function 数据库名.函数名;

永久函数

永久函数一旦注册,可以在hive cli,远程连接hiveserver2等地方永久使用,步骤为:

  • 先上传jar包到HDFS

  • 永久注册:

CREATE FUNCTION 函数名 AS '包名.类名' USING JAR 'hdfs:///path/xxxx.jar';

注意:指定jar包路径需要是hdfs路径。

  • 删除永久函数:
drop function 数据库名.函数名字;

新增的永久函数,比如在hive cli命令行注册的,可能会在beeline或者hiveserver2远程连接时,提示不存在该函数。解决办法是,在无法使用UDF的HiveServer2上,执行reload function命令,将MetaStore中新增的UDF信息同步到HiveServer2内存中。

场景

UDF在hive中使用场景广泛,这里列举常用的使用场景。

IP 转化为地址

分词

SQL 分析UDF

Hive中的UDF详解的更多相关文章

  1. 大数据学习系列之五 ----- Hive整合HBase图文详解

    引言 在上一篇 大数据学习系列之四 ----- Hadoop+Hive环境搭建图文详解(单机) 和之前的大数据学习系列之二 ----- HBase环境搭建(单机) 中成功搭建了Hive和HBase的环 ...

  2. Hive 的collect_set使用详解

    Hive 的collect_set使用详解   https://blog.csdn.net/liyantianmin/article/details/48262109 对于非group by字段,可以 ...

  3. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. AngularJS select中ngOptions用法详解

    AngularJS select中ngOptions用法详解   一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...

  6. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  7. oracle中imp命令详解 .

    转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...

  8. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  9. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

随机推荐

  1. 慢SQL优化:where id in (select max(id)...) 改为join后性能提升400倍

    背景 有两张表,都是主键递增,类似于主表和明细表: statistics_apply:统计申请表,主键applyId,7万多条记录 statistics_apply_progress:统计申请进度表( ...

  2. Java基础知识面试题(最详细版)

    刚刚经历过秋招,看了大量的面经,顺便将常见的Java常考知识点总结了一下,并根据被问到的频率大致做了一个标注.一颗星表示知识点需要了解,被问到的频率不高,面试时起码能说个差不多.两颗星表示被问到的频率 ...

  3. CenOS下监控工具尝试

    Cacti cacti重图形,有数据历史,需要用到数据库支持,支持web配置,默认不支持告警,可以加插件. Server端配置 安装epel yum install -y epel-release 安 ...

  4. python:列表的去重:两种方法的问题是:结果是没有保持原来的顺序。

    列表的去重 1.使用set的特型,python的set和其他语言类似, 是一个无序不重复元素集 orgList = [1,0,3,7,7,5] #list()方法是把字符串str或元组转成数组 for ...

  5. 避开一部分安装问题的Burpsuite的安装教程

    Burpsuite的安装教程 前言: 既然网上有很多的Burpsuite的安装教程为什么笔者还要在写这篇文章呢? 笔者发现网上的许多安装教程都存在着许许多多的问题,有时候对于一些安装细节描述不是很深, ...

  6. day3(使用axios实现登录成功)

    1.创建一个login.vue页面 1.1写页面components/Login.vue 在 src/components 下创建 Login.vue 页面 <template>   &l ...

  7. MySQL索引(一)索引基础

    索引是数据库系统里面最重要的概念之一.一句话简单来说,索引的出现其实是为了提高数据查询的效率,就像书的目录一样. 常见模型 索引的出现是为了提高查询效率,但是实现索引的方式却有很多种,这里就介绍三种常 ...

  8. Django 框架基本操作(二)

    一.设计表结构 1.班级表结构 表名:grade 字段:班级名称(gname).成立时间(gdate).女生总数(ggirlnum).男生总数(gboynum).是否删除(isDelete) 2.学生 ...

  9. scrapy爬取微信小程序社区教程(crawlspider)

    爬取的目标网站是: http://www.wxapp-union.com/portal.php?mod=list&catid=2&page=1 目的是爬取每一个教程的标题,作者,时间和 ...

  10. 堆叠注入tips

    漏洞成因 使用mysqli_multi_query()这种支持多语句执行的函数 使用PDO的方式进行数据查询,创建PDO实例时PDO::MYSQL_ATTR_MULTI_STATEMENTS设置为tr ...