Hive 内置函数及自定义函数
1.内置函数
使用如下命令查看当前hive版本支持的所有内置函数
show functions;
部分截图:
可以使用如下命令查看某个函数的使用方法及作用,比如查看 upper函数
desc function upper;
如果想要查看更为详细的信息加上extended参数
desc function extended upper;
内置函数使用
员工表emp,数据如下
- lower():转换为小写
查询emp表中员工姓名,员工姓名小写显示
select empno,ename,lower(ename) from emp;
- 字符串连接:concat()
查询emp表,将员工姓名追加到员工编号后
select empno,ename,concat(empno,ename) from emp;
hive中的内置有很多,在这笔者就不再一一介绍,如果在使用过程中遇到问题可以使用命令来查看该函数的使用方法及作用,或查看官方使用文档:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
2.自定义函数
虽然hive中为我们提供了很多的内置函数,但是在实际工作中,有些情况下hive提供的内置函数无法满足我们的需求,就需要我们自己来手动编写,所以就有了自定义函数 UDF。
UDF分为三种,分别如下
(1).UDF(User-Defined-Function),一进一出(输入一行,输出一行),比如:upper()、lowser()等。
(2).UDAF(User-Defined Aggregation Funcation),多进一出(输入多行,输出一行),比如:avg()、sum()等。
(3).UDTF(User-Defined Table-Generating Functions),一进多出(输入一行,输出多行),比如:collect_set()、collect_list()等。
官方文档:https://cwiki.apache.org/confluence/display/Hive/HivePlugins
使用自定义函数需要引入hive-exec的依赖
<dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>2.3.0</version>
</dependency>
1.自定义UDF函数
UDF编程模型:
(1).继承 org.apache.hadoop.hive.ql.exec.UDF
(2).实现 evaluate() 方法
实现需求:自定义UDF函数,给指定的字符串前加上字符串hello:
比如:输入zhangsan,输出hello:zhangsan
代码:
package com.bigdata.hadoop.hive;import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;/*** 自定义UDF函数* 输入:Tom* 输出:hello:Tom*/
@Description(name = "say_hello,ucase",value = "_FUNC_(str) - Returns str start with hello:",extended = "Example:\n > SELECT _FUNC_(\'Facebook\') FROM src LIMIT 1;\n \'hello:Facebook\'"
)
public class GenericUDFHello extends UDF {public String evaluate (final Text s){if (s == null) {return null;}return "hello:" + s.toString();}public static void main(String[] args) {System.out.println(new GenericUDFHello().evaluate(new Text("Tom")));}
}
自定义函数有4种使用方式,下面笔者分别来介绍
- 方式一(临时函数,只能在当前客户端使用)
将我们刚刚编写完成的代码,打成jar
将jar包上传到hive
add jar /home/hadoop/libs/hive-1.0-SNAPSHOT.jar;
创建函数
create temporary function say_hello as 'com.bigdata.hadoop.hive.GenericUDFHello';
查看创建的函数say_hello
show functions;
查看函数say_hello的详细信息
desc function extended say_hello;
使用函数
select ename,say_hello(ename) from emp;
- 方式二(临时函数,只能在当前客户端使用)
在$HIVE_HOME下新建目录auxlib,将jar拷贝到该目录下,重启hadoop
$ cd $HIVE_HOME
$ mkdir auxlib
$ cd auxlib/
$ cp /home/hadoop/libs/hive-1.0-SNAPSHOT.jar .
创建函数say_hello2
create temporary function say_hello2 as 'com.bigdata.hadoop.hive.GenericUDFHello';
查看创建的函数,同上
使用函数,效果同上
select ename,say_hello2(ename) from emp;
- 方式三(永久函数,创建后可以在任意客户端使用,建议使用)
上传jar到hdfs
$ hadoop fs -put hive-1.0-SNAPSHOT.jar /libs
创建函数 say_hello3
create function say_hello3 as 'com.bigdata.hadoop.hive.GenericUDFHello' using jar 'hdfs://hdpcomprs:9000/libs/hive-1.0-SNAPSHOT.jar';
注意:创建完function之后,通过show functions并没有看到我们自定义的函数say_hello3,但是可以使用
使用函数,效果同上
select ename,say_hello3(ename) from emp;
- 方式四(永久函数,将自定义函数集成到hive源码中)
使用这种方式需要修改hive的源代码,集成到hive源码后,hive启动后就可以使用,不用再向hive中注册函数,相当于一个hive的内置函数。如果公司有自己的大数据框架版本,建议使用这种方式。
从官网下载hive源码,笔者使用的版本为2.3.0,http://apache.fayea.com/hive/
下载后解压
$ tar -zxvf apache-hive-2.3.0-src.tar.gz
将自定义UDF函数继承到Hive源码中,需要如下三个步骤
(1).上传文件
把GenericUDFHello.java类上传到如下目录,并修改包名
$ cd apache-hive-2.3.0-src/ql/src/java/org/apache/hadoop/hive/ql/udf
$ rz
$ vim GenericUDFHello.java
package org.apache.hadoop.hive.ql.udf;
(2).配置FunctionRegistry类
hive 中有一个非常重要的类FunctionRegistry,我们需要将自己自定义的函数在这个类中配置,引入我们自定义函数类GenericUDFHello
$ cd apache-hive-2.3.0-src/ql/src/java/org/apache/hadoop/hive/ql/exec
$ vim FunctionRegistry.java
import org.apache.hadoop.hive.ql.udf.GenericUDFHello;
注册自定义函数类GenericUDFHello,输入static { 搜索,在静态代码块中注册我们编写的自定义函数,这里面都是hive的所有内置函数,添加如下代码
system.registerUDF("hello", GenericUDFHello.class, false);
(3).编译 Hive 源码
$ cd apache-hive-2.3.0-src
$ mvn clean package -Phadoop-2,dist -DskipTests
-Phadoop-2表示使用的hadoop版本为2,如果为1,则写-Phadoop-1
编译过程教程,请耐心等待,编译完成后,hive会生成一个压缩包,解压配置后就可以使用,hive压缩包存放的路径是apache-hive-2.3.0-src/packaging/target
使用函数hello(效果同上)
select empno,ename,hello(ename) from emp;
如果你在编译Hive的源码时,遇到错误,可以参考博客:
http://blog.csdn.net/HG_Harvey/article/details/77806542
2.自定义UDAF函数
UDAF编程模型
(1).继承 org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
(2).实现 evaluate() 方法
(3).编写静态内部类(函数的计算逻辑),继承GenericUDAFEvaluator,必须重写如下方法
UDAF同样有四种使用方式(参照自定义函数UDF中的介绍)
实现需求:计算表中某列字母的个数
代码:
package com.bigdata.hadoop.hive;import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;/*** 自定义UDAF函数* 计算表中某列字母的个数*/
@Description(name = "numofletters",value = "_FUNC_(x) - Returns the total number of characters of all the strings in that column"
)
public class GenericUDAFTotalNumOfLetters extends AbstractGenericUDAFResolver {// 返回聚合函数在经过map combiner reduce 的阶段时使用的计算器@Overridepublic GenericUDAFEvaluator getEvaluator(TypeInfo[] info) throws SemanticException {return new TotalNumOfLettersEvaluator();}// 静态内部类,聚合函数的计算逻辑public static class TotalNumOfLettersEvaluator extends GenericUDAFEvaluator{//两个输入类型一个输出类型ObjectInspector out;PrimitiveObjectInspector text,num;// map combiner reduce 的阶段都会执行的方法@Overridepublic ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {super.init(m, parameters);// 注释掉则整个程序将无法执行// 表示正在执行 map 阶段if(m == Mode.PARTIAL1 || m==Mode.COMPLETE){//保存计算map输入的数据类型,即sql类型text= (PrimitiveObjectInspector) parameters[0];}else { //表示正在执行 combiner 或者 reduce//保存计算的 combiner 或者 reduce 阶段的输入数据类型num = (PrimitiveObjectInspector) parameters[0];}out= ObjectInspectorFactory.getReflectionObjectInspector(Integer.class,ObjectInspectorFactory.ObjectInspectorOptions.JAVA);return out;}// 会根据mode决定调用merge还是iterate@Overridepublic void aggregate(AggregationBuffer agg, Object[] parameters) throws HiveException {super.aggregate(agg, parameters);}// 保存当前字符总数的静态内部类static class LetterSumAgg implements AggregationBuffer{int sum;public void add(int num){sum+=num;}}//计算器在阶段处理中用来获取一个新的中间存储对象public AggregationBuffer getNewAggregationBuffer() throws HiveException {LetterSumAgg letterSumAgg = new LetterSumAgg();return letterSumAgg;}// 重置阶段中存储的数据,清除public void reset(AggregationBuffer aggregationBuffer) throws HiveException {LetterSumAgg letterSumAgg = new LetterSumAgg();}// map计算阶段迭代统计字符个数public void iterate(AggregationBuffer aggregationBuffer, Object[] parameters) throws HiveException {if (parameters[0] != null) {LetterSumAgg letterSumAgg = (LetterSumAgg) aggregationBuffer;Object p1 = text.getPrimitiveJavaObject(parameters[0]);letterSumAgg.add(String.valueOf(p1).length());}}// 返回一个map或combiner阶段计算器统计的结果,即map或combiner的输出public Object terminatePartial(AggregationBuffer aggregationBuffer) throws HiveException {return ((LetterSumAgg)aggregationBuffer).sum;}// 计算器在被combiner或者reduce阶段执行时调用,合并之前阶段的部分统计结果public void merge(AggregationBuffer aggregationBuffer, Object partial) throws HiveException {if (partial != null) {LetterSumAgg letterSumAgg = (LetterSumAgg) aggregationBuffer;Integer partialSum = (Integer) num.getPrimitiveJavaObject(partial);letterSumAgg.add(partialSum);}}// 计算器在被reduce阶段执行时调用,合并之前阶段的部分统计结果,最终返回确定的结果输出public Object terminate(AggregationBuffer aggregationBuffer) throws HiveException {return ((LetterSumAgg) aggregationBuffer).sum;}}
}
上传jar到hive
add jar /home/hadoop/libs/hive-1.0-SNAPSHOT.jar;
创建临时函数
create function numofletters as 'com.bigdata.hadoop.hive.GenericUDAFTotalNumOfLetters';
查看创建的临时函数
show functions;
查看函数的详细信息
desc function numofletters;
使用函数
tb_test 表中数据如下
计算emp表中ename列字母个数(会执行mapreduce作业)
select numofletters(language) from tb_test;
3.自定义UDTF函数
(1).继承 org.apache.hadoop.hive.ql.udf.generic.GenericUDTF
(2).实现三个方法 initialize()、process()、close()
UDTF也有四种使用方式(参照自定义函数UDF中的介绍)
实现需求:切分map
输入:key1:value1;key2:value2;
输出:key1 value1 key2 value2
代码:
package com.bigdata.hadoop.hive;import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;import java.util.ArrayList;/*** 自定义UDTF函数* 切分map* 输入:math:80;chinese:89;english:95;* 输出:math,80 chinese,89 english,95*/
@Description(name = "split_map",value = "_FUNC_(x) - input key1:value1;key2:value2; output key1,value1 key2,value2"
)
public class GenericUDTFSplitMap extends GenericUDTF {// 初始化校验参数是否正确@Overridepublic StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {if (args.length != 1) {throw new UDFArgumentLengthException("ExplodeMap takes only one argument");}if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {throw new UDFArgumentException("ExplodeMap takes string as a parameter");}ArrayList<String> fieldNames = new ArrayList<String>();ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();fieldNames.add("col1");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);fieldNames.add("col2");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs);}// 函数逻辑处理,并将结果返回(forward)@Overridepublic void process(Object[] args) throws HiveException {String input = args[0].toString();// 按分号分隔String[] strings = input.split(";");for(int i=0; i<strings.length; i++) {try {// 按冒号分隔String[] result = strings[i].split(":");forward(result);} catch (Exception e) {continue;}}}// 对需要清理的方法进行清理@Overridepublic void close() throws HiveException {}
}
上传jar到hive中
add jar /home/hadoop/libs/hive-1.0-SNAPSHOT.jar;
创建函数
create function split_map as 'com.bigdata.hadoop.hive.GenericUDTFSplitMap';
使用函数
tb_udtf表中数据如下
select split_map(scores) as (subject,score) from tb_udtf;
Hive 内置函数及自定义函数相关推荐
- 大数据入门教程系列之Hive内置函数及自定义函数
本篇文章主要介绍Hive内置函数以及自定义UDF函数和UDFT函数,自定义UDF函数通过一个国际转换中文的例子说明. 操作步骤: ①.准备数据和环境 ②.演示Hive内置函数 ③.自定义UDF函数编写 ...
- Hive函数(内置函数(字符串函数,数学函数,日期函数,集合函数,条件函数,聚合函数,表生成函数)和自定义函数(自定义函数创建流程,临时函数,永久函数)))(四)
Hive函数(内置函数和自定义函数) 一.内置函数 1.字符串函数 (1)ascii (2)base64 (3)concat (4)concat_ws (5)format_number (6)subs ...
- Hive内置函数与常用函数汇总
目录 Hive内置函数汇总 字符函数(字符串操作) 数学函数 集合函数 类型转换函数 日期函数 条件函数 聚合函数 表生成函数 辅助功能类函数 数据屏蔽函数(从Hive 2.1.0开始) Hive常用 ...
- 内置函数、自定义函数
编程语言的函数都可以分为两类:内置函数和自定义函数. 内置函数分为 数字相关的内置函数 # abs(x) 求绝对值print(abs(-10)) #10 """ divm ...
- hive内置函数大全
在学习hive过程中,熟练使用hive内置函数,可以节省大量时间,在学习之余,将函数基本使用总结汇总一下,方便后续使用查阅,混个脸熟,内置函数271个,结合源码,需要持续学习更新 分享一个全面的函数大 ...
- Hive—内置date函数用法详解
关注微信公众号:CodingTechWork,一起学习进步. 引言 在hive中我们经常需要处理日期数据,hive内置了3个日期函数,其格式只能为yyyy-MM-dd格式或者yyyy-MM-dd ...
- Hive学习之路(四):Hive内置函数介绍与实现WordCount
内容简介 一.Hive内置函数介绍 二.Hive常用内置函数介绍 1.数值计算函数 2.字符串操作函数 3.日期函数 4.聚合函数 5.表生成函数 三.使用Hive函数完成WordCount 1.创建 ...
- Hive之函数与自定义函数
系统自带的函数 1)查看系统自带的函数hive> show functions; 2)显示自带的函数的用法hive> desc function upper; 3)详细显示自带的函数的用法 ...
- Python 函数式编程,Python中内置的高阶函数:map()、reduce()、filter()与sorted(),Python中返回函数
函数式编程 是一种编程范式,比函数更高层次的抽象. 函数式编程将计算视为函数而非指令. 纯函数式编程:不需要变量,没有副作用,测试简单. 支持高阶函数,代码简洁. Python 支持的函数式编程 不是 ...
最新文章
- 分支定义之Trunk vs Master
- win10死机频繁怎么解决
- qq饥荒联机版服务器没有响应,饥荒联机版专用服务器卡顿原因及解决方法汇总...
- 分离了sa默认的数据库 , 用sa登录不了的解决方法
- 在AppWeb后台,管理员所有数据已经录入完毕,但用手机浏览器登录评委打分界面,发现打分界面为空,或者选手人数不对等问题,如何解决?
- 《指针的编程艺术(第二版)》一2.3 三颗星星:表示三把钥匙
- 抖音云蹦迪源码/很火的直播打赏类项目源码
- 安装phantomjs、使用phantomjs以及时遇到问题时的解决方法
- sodp软件如何导入多个工作面信息_如何批量导入数据到手机通讯录
- 计算机文化与社会发展
- 踩了个DNS解析的坑,但我还是没想通
- REST Assured 使用详解
- 六级考研单词之路-十六
- 解决双屏切换为单屏,打开的软件窗口无法显示问题
- HX711测试【一个非常廉价且实用的模块】
- 15 三极管主要参数
- 计算机系统如何恢复出厂设置路由器,路由器恢复出厂设置的具体操作步骤-电脑自学网...
- MySQL SQL语句 生成32位 UUID
- 华科计算机保研复试题目,华科计算机保研复试机试题目2.doc
- 二目运算符是什么意思?