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 理 ...
随机推荐
- Swift-字符串
1.字符串的遍历 //NSString 不支持一下字符串的遍历 let str = "我要飞的更高" for c in str.characters{ print(c) } 2.字 ...
- hibernate课程 初探单表映射3-1 hibernate单表操作简介
本章简介: 1 单一主键 2 基本类型 3 对象类型 4 组件属性 5 单表操作CRUD实例
- 安装mysql-installer-community
1.在官网上下载mysql-installer-community-5.6.25.0 2.选择MySQL Installer 3.选择Windows (x86, 32-bit), MSI Instal ...
- vue-elem-stylus 的mixin用法
.tab border-1px{red} minxin border-1px(&color) position:relative &::after display:block posi ...
- SVG矢量图【转】
var iconArray=[ //'circle', //实心圆 //'rect', //矩形 //'roundRect', //圆角矩形 //'triangle', //三角形 //'diamon ...
- form表单多文件上传
1.html/jsp主页 <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:9.观察者模式
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 前言 在一个程序的迭代过程中,复杂度渐渐上升,可能会出现一些跨模块的调用的需求,若是直接得到引用来进行使用,会导致模 ...
- python 多线程 生产者消费者
import threading import time import logging import random import Queue logging.basicConfig(level=log ...
- C#实现正则表达式
如果想了解正则表达式的基础知识:http://www.cnblogs.com/alvin-niu/p/6430758.html 一.C#中的Regex类 1.在C#中开发正则表达式,首先要引用Syst ...
- webpack前端构建工具学习总结(二)之loader的使用
Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换. Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为 ...