Hive UDTF开发指南
在这篇文章中,我们将深入了解用户定义表函数(UDTF),该函数的实现是通过继承org.apache.Hadoop.hive.ql.udf.generic.GenericUDTF这个抽象通用类,UDTF相对UDF更为复杂,但是通过它,我们读入一个数据域,输出多行多列,而UDF只能输出单行单列。
代码
文章中所有的代码可以在这里找到:hive examples、GitHub repository
示例数据
- ~$ cat ./people.txt
- John Smith
- John and Ann White
- Ted Green
- Dorothy
把该文件上载到hdfs目录/user/matthew/people中:
- hadoop fs -mkdir people
- hadoop fs -put ./people.txt people
下面要创建hive外部表,在hive shell中执行
- CREATE EXTERNAL TABLE people (name string)
- ROW FORMAT DELIMITED FIELDS
- TERMINATED BY '\t'
- ESCAPED BY ''
- LINES TERMINATED BY '\n'
- STORED AS TEXTFILE
- LOCATION '/user/matthew/people';
UDTF的输出值
以上所有的要求我们可以用UDTF去完成。
实例
首先我们先假设我们想清洗people这张表中的人名,这个新的表有:
1、姓和名 两个分开的列
2、所有记录都包含姓名
3、每条记录或有包含多个人名(eg Nick and Nicole Smith)
- org.apache.hadoop.hive.ql.udf.generic.GenericUDTF
我们将覆盖以下三个方法:
- //该方法中,我们将指定输入输出参数:输入参数的ObjectInspector与输出参数的StructObjectInspector
- abstract StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException;
- //我们将处理一条输入记录,输出若干条结果记录
- abstract void process(Object[] record) throws HiveException;
- //当没有记录处理的时候该方法会被调用,用来清理代码或者产生额外的输出
- abstract void close() throws HiveException;
代码实现
完整代码
- public class NameParserGenericUDTF extends GenericUDTF {
- private PrimitiveObjectInspector stringOI = null;
- @Override
- public StructObjectInspector initialize(ObjectInspector[] args) UDFArgumentException {
- if (args.length != 1) {
- throw new UDFArgumentException("NameParserGenericUDTF() takes exactly one argument");
- }
- if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE
- && ((PrimitiveObjectInspector) args[0]).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {
- throw new UDFArgumentException("NameParserGenericUDTF() takes a string as a parameter");
- }
- // 输入格式(inspectors)
- stringOI = (PrimitiveObjectInspector) args[0];
- // 输出格式(inspectors) -- 有两个属性的对象
- List<String> fieldNames = new ArrayList<String>(2);
- List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(2);
- fieldNames.add("name");
- fieldNames.add("surname");
- fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
- fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
- return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
- }
- public ArrayList<Object[]> processInputRecord(String name){
- ArrayList<Object[]> result = new ArrayList<Object[]>();
- // 忽略null值与空值
- if (name == null || name.isEmpty()) {
- return result;
- }
- String[] tokens = name.split("\\s+");
- if (tokens.length == 2){
- result.add(new Object[] { tokens[0], tokens[1] });
- }else if (tokens.length == 4 && tokens[1].equals("and")){
- result.add(new Object[] { tokens[0], tokens[3] });
- result.add(new Object[] { tokens[2], tokens[3] });
- }
- return result;
- }
- @Override
- public void process(Object[] record) throws HiveException {
- final String name = stringOI.getPrimitiveJavaObject(record[0]).toString();
- ArrayList<Object[]> results = processInputRecord(name);
- Iterator<Object[]> it = results.iterator();
- while (it.hasNext()){
- Object[] r = it.next();
- forward(r);
- }
- }
- @Override
- public void close() throws HiveException {
- // do nothing
- }
- }
以上代码可以从:github目录 check 下来。
代码走读
我们为输入的string参数定义了数据格式PrimitiveObjectInspector
- stringOI = (PrimitiveObjectInspector) args[0]
定义输出数据格式(objectinspectors) 需要我们先定义两个属性名称,因为(objectinspectors)需要读取每一个属性(在这个实例中,两个属性都是string类型)。
- List<String> fieldNames = new ArrayList<String>(2);
- fieldNames.add("name");
- fieldNames.add("surname");
- List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(2);
- fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
- fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
- return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
我们主要的处理逻辑放在这个比较直观的processInputRecord方法当中。分开逻辑处理有利我们进行更简单的单元测试,而不用涉及到繁琐的objectinspector。
- while (it.hasNext()){
- Object[] r = it.next();
- forward(r);
- }
- }
使用该UDTF函数
我们可以在hive中创建我们自己的函数
- mvn package
- cp target/hive-extensions-1.0-SNAPSHOT-jar-with-dependencies.jar ./ext.jar
然后在hive中使用
- ADD JAR ./ext.jar;
- CREATE TEMPORARY FUNCTION process_names as 'com.matthewrathbone.example.NameParserGenericUDTF';
- SELECT
- adTable.name,
- adTable.surname
- FROM people
- lateral view process_names(name) adTable as name, surname;
输出
- OK
- John Smith
- John White
- Ann White
- Ted Green
原文链接
Hive UDTF开发指南的更多相关文章
- 最强最全面的Hive SQL开发指南,超四万字全面解析
本文整体分为两部分,第一部分是简写,如果能看懂会用,就直接从此部分查,方便快捷,如果不是很理解此SQL的用法,则查看第二部分,是详细说明,当然第二部分语句也会更全一些! 第一部分: hive模糊搜索表 ...
- Hive UDF开发指南
编写Apache Hive用户自定义函数(UDF)有两个不同的接口,一个非常简单,另一个...就相对复杂点. 如果你的函数读和返回都是基础数据类型(Hadoop&Hive 基本writable ...
- ASP.NET Aries 开源开发框架:开发指南(一)
前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...
- FreeMarker模板开发指南知识点梳理
freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...
- Jetty使用教程(四:21-22)—Jetty开发指南
二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...
- JVM 平台上的各种语言的开发指南
JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...
- iOS原生地图开发指南续——大头针与自定义标注
iOS原生地图开发指南续——大头针与自定义标注 出自:http://www.sxt.cn/info-6042-u-7372.html 在上一篇博客中http://my.oschina.net/u/23 ...
- Angularjs中文版本开发指南发布
从本人开始在写关于Angularjs的文章开始,也算是见证了Angularjs在国内慢慢的火起来,如今的Angularjs正式如日中天.想知道为什么Angularjs会这么火,请移步angularjs ...
- nodejs开发指南读后感
nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...
随机推荐
- 开始使用JQuery 方法
使用jQuery需要3个基本步骤: 1. 下载jQuery.js并保存在网页可以存取的位置.下载链接:dowload 2. 在HTML的head里引用jQuery.js 3. 运用jQuery的方法 ...
- db2一些简单操作及错误记录
操作: 删除主键: alter table tablename drop parimary key 添加主键: alter table tablename add primary key(colum ...
- Intellij IDEA 最头大的问题,如何自定义注释模板?
想栈长我当初从 Eclipse 转用 IDEA 真是纠结,放弃然后尝试了N次,不过现在已经算是转型成功了,可以完全脱离 Eclipse 撸码了,虽然说我现在真的撸得非常少了.. 说到 IDEA 的痛点 ...
- 一起来学Spring Cloud | 第一章 :如何搭建一个多模块的springcloud项目
在spring cloud系列章节中,本来已经写了几个章节了,但是自己看起来有些东西写得比较杂,所以重构了一下springcloud的章节内容,新写了本章节,先教大家在工作中如何搭建一个多模块的spr ...
- vue安装及环境搭建
vue项目在pycharm里运行需要安装一个插件,打开settings,找到plugins,里面搜索vue.js,点击安装. vue安装 先安装node.js npm install -g @vue/ ...
- Unity3d 游戏中集成Firebase 统计和Admob广告最新中文教程
之前写过俩相关的教程,最近发现插件官方更新了不少内容,所以也更新一篇Firebase Admob Unity3d插件的教程,希望能帮到大家. Firebase Admob Unity3d插件是一个Un ...
- Windows 10 下使用Git
事实上,比在Linux下要难很多.不仅仅是因为Linux下CMD功能较弱,还有就是国内的网络环境,至少,我这Github Windows安装时,总是会下载无法完成 Github Desktop 虽然, ...
- spring 中使用quartz实现定时任务
一般开发系统,使用定时任务非常常见.当然也可以用Java实现.比如定时器.大致如下: 1: public static void main(String[] args) { 2: Timer time ...
- 性能调优--大事务与Alwayson 之间的关系
最近性能调优的事比较多,所以摘一些比较有特点的 案例分享下. 业务系统用的是sql server 2016 ,搭建的ALWAYSON 两节点的 群集,今天早上突然辅助 副本的只读库出现大量的等待导致系 ...
- sql server 2016新特性 查询存储(Query Store)的性能影响
前段时间给客户处理性能问题,遇到一个新问题, 客户的架构用的是 alwayson ,并且硬件用的是4路96核心,内存1T ,全固态闪存盘,sql server 2016 . 问题 描述 客户经常出现 ...