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 理 ...
随机推荐
- JS 分页实现
var pagesize = 5; var pageindex = 1; var pagetype; var parms; var nextSize = 1; var target; function ...
- JMeter测试TCP服务器遇到的一个奇怪问题
今天工作需要测TCP服务器的压力,因为tsung测试TCP需要写的脚本实在头大,于是换了JMETER来搞压力测试.在实际测试的过程中,遇到了一个很奇怪的问题,就是发了数据包以后,JMeter不停地报5 ...
- OpenStack Ocata Telemetry 警告服务部署
下列操作在控制节点上进行: 1 准备条件 在配置OpenStack Telemetry服务之前,你必须创建数据库.服务凭证和API端点. 1.1 数据库 以root用户连接数据库服务器,创建glanc ...
- 分布式缓存memcached介绍,win7环境安装,常用命令set,get,delete,stats, java访问
一.memcached是什么? 二.memcached不互相通信的分布式 三.安装步骤 四.本文介绍的命令主要包括: 存入命令(Storage commands) 取回命令(Retrieval com ...
- Asp.net MVC 服务端验证多语言错误
服务端验证用户提交信息时为了实现多语言使用了资源文件,如: using System.ComponentModel.DataAnnotations; public class UserModel { ...
- jsop解析获得htmldome
package com.open1111.jsoup; import org.apache.http.HttpEntity;import org.apache.http.client.methods. ...
- [Rails学习之路]Rails文件结构与路由
约定优于配置和RESTful是Ruby on Rails十分推崇的哲学.在一个默认的RESTful的Rails项目中,使用资源和HTTP动词来帮助组织项目. 假如有一个使用scaffold创建的Rai ...
- POJ 1065 Wooden Sticks(LIS,最少链划分)
题意:求二维偏序的最少链划分. 用到Dilworth定理:最少链划分=最长反链.(对偶也成立,个人认为区别只是一个维度上的两个方向,写了个简单的证明 相关概念:偏序集,链,反链等等概念可以参考这里:h ...
- 2018.6.5 Oracle plsql编程 游标的使用
--3.查询10部门所有员工的姓名.(ref游标实现) 动态游标 declare --创建一种游标类型 type type_cursor is ref cursor; --声明变量指定游标类型 v_c ...
- 深入理解计算机系统_3e 第十一章家庭作业 CS:APP3e chapter 11 homework
注:tiny.c csapp.c csapp.h等示例代码均可在Code Examples获取 11.6 A. 书上写的示例代码已经完成了大部分工作:doit函数中的printf("%s&q ...