大数据平台搭建(四):hive中的表及UDF

原创 2018年04月13日 21:07:17

前言

     本章介绍hive内部表、外部表、分区表和UDF等。

1.hive表介绍

    1.Hive虽说是数据仓库,其实可以认为就是一个mysql数据库,hive中的表名对应的是hdfs上的文件目录名,表内容就是对应目录下的文件。
    2.hive表的hdfs路径
     在hive-site.xml中,由参数hive.metastore.warehouse.dir指定,我的是/hivedata/warehouse。
     

2. 应用场景

     1.每天将收集到的网站日志定期流入HDFS文本文件,一天一个目录;
     2.在Hive中建立内部分区表,通过添加分区的方式,将每天HDFS上的原始日志映射到表的分区中;
     3.在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT。

3.内部表

     1.vim student.txt,并hadoop fs -put student.txt 上传到hdfs,举例(用’\t’间隔):

这里写图片描述

     2.创建内部表指定分隔符:
     create table student (id bigint,name string,age double,sex string) row format delimited fields terminated by ‘\t’;
     3.从hdfs load数据到表中:
     load data local inpath ‘hdfs://mycluster/test/student.txt’ into table student
     4.查询数据:

这里写图片描述
     注意:此时student.txt 被移走了!

4.外部表

     1.创建外部表,关键字:external location
       create external table student_ext (id bigint,name string,age double,sex string) row format delimited fields terminated by ‘\t’ location ‘/test/data/’。
    2. /test/data/目录下所有数据都会被加载进来,但是hive表目录下没有新目录创建。

这里写图片描述
这里写图片描述

5.外部表和内部表区别

     1.DROP时不同:内部表DROP时候会删除HDFS上的数据; 外部表DROP时候不会删除(类似于挂载的其他路径)HDFS上的数据;
    2.适用场景不同:外部表需要定期将外部数据映射到表中,内部表一般作为中间表和结果表,比如外部表统计后的结果用内部表存储。
    3.外部表要使用关键字 external 和 location(创建表可以不指定,增加分区需要)。

6.分区表

    1.分区表其实就是数据量太大,将数据分不同目录来存储,统计时查询比较快。个人觉得分区表跟内部表和外部表没有什么关系,一定区分开来。
    2.创建分区表
     create table people (id bigint, name string) partitioned by (nation string) row format delimited fields terminated by ‘\t’;
    3.load数据到分区表(会移走源文件)
     load data inpath ‘hdfs://mycluster/test/data/china.txt’ into table people partition(nation=’China’)

这里写图片描述

      load的方式会在hive中生成对应的分区目录,且目录下有数据。

这里写图片描述

    4.直接增加分区,hive目录下不会产生分区目录。
     alter table people5 add partition(nation=’China’) location ‘/China’;

这里写图片描述

    5.说的再多不如自己一试,没接触过的可能觉得有点晕,自己试一下就知道了!

7.UDF

    hive中,除了提供丰富的内置函数外,还允许用户自己定义UDF函数。
    开发自定义UDF函数有三种方式:
     1.继承org.apache.hadoop.hive.ql.exec.UDF;
     2.继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
     3.通过脚本的方式,比如python UDF、scala UDF等。
     简单的数据类型(比如String、Integer等)可以用UDF,复杂的数据类型(Array、Map、Struct)可以使用GenericUDF,或者通过脚本实现函数体。
    比如,我们有个需求:消费2000元以上的评级为A,其他的评级为B,先来看下表中数据如下:

这里写图片描述

    UDF实现
      1.eclipse创建maven项目hive,引入依赖:
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.cnepay</groupId>
  <artifactId>hive</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hive</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>1.1.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>2.6.0</version>
        <!-- <scope>provided</scope> -->
    </dependency>
    <dependency>
        <groupId>jdk.tools</groupId>
        <artifactId>jdk.tools</artifactId>
        <version>1.6</version>
        <scope>system</scope>
        <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
    </dependency>


    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
      2.java代码
package com.cnepay.hive;

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

public class CountFee extends UDF{
    private Text t = new Text();

    public Text evaluate(Double fee){

        if(fee >= 2000.0){
            t.set("A");
        }
        else{
            t.set("B");
        }

        return t;
    }
}
      3.将项目打成jar,并上传到Linux服务器

这里写图片描述

      4.进入hive或beeline命令行,
        a.将jar包加入到hive的classpath: add jar /home/hadoop/countFee.jar;
        b.创建临时函数:create temporary function getFee as ‘com.cnepay.hive.CountFee’;

这里写图片描述

     GenericUDF实现
     1.继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF之后,必须需要重写3个重要的方法:
      public ObjectInspector initialize(ObjectInspector[] arguments)
      //必选,该方法用于函数初始化操作,并定义函数的返回值类型;
      public Object evaluate(DeferredObject[] args){}
      //必选,函数处理的核心方法,用途和UDF中的evaluate一样;
      public String getDisplayString(String[] children)
      //必选,显示函数的帮助信息
     2.java代码,关注下代码中注释
package com.cnepay.hive;

import java.util.ArrayList;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
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 org.apache.hadoop.io.Text;

public class WxqGenericUDF extends GenericUDF{

    private Object[] ret = new Object[2];

    /**
     * 作用:
     * 1.检查输入类型是否正确;
     * 2.初始化读取文件等操作;
     * 3.定义函数的返回值类型是对象;
     * 
     */
    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments)
            throws UDFArgumentException {
        //检查输入参数个数
        if(arguments.length != 2){
            throw new UDFArgumentException(" The function 'WxqGenericUDF' accepts 2 argument !");
        }

        //存储struct对象的属性名称
        ArrayList<String> structFieldNames = new ArrayList<>();
        //存储struct对象的属性值的类型
        ArrayList<ObjectInspector> structFieldObjectInspectors = new ArrayList<>();

        //创建两个属性,name 和 level
        structFieldNames.add("name");
        structFieldNames.add("level");

        //定义name和level值的类型为string
        structFieldObjectInspectors.add(PrimitiveObjectInspectorFactory.writableStringObjectInspector);
        structFieldObjectInspectors.add(PrimitiveObjectInspectorFactory.writableStringObjectInspector);

        //定义函数的返回类型是struct对象
        StructObjectInspector soi = ObjectInspectorFactory.getStandardStructObjectInspector(structFieldNames, structFieldObjectInspectors);

        return soi;
    }

    /**
     * 遍历每条记录
     */
    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        String name = arguments[0].get().toString();
        Double fee = Double.parseDouble(arguments[1].get().toString());

        //编写具体业务逻辑,封装返回对象。
        ret[0] = new Text(name);
        if(fee >= 2000.0){
            ret[1] = new Text("A");
        }
        else{
            ret[1] = new Text("B");
        }


        return ret;
    }

    @Override
    public String getDisplayString(String[] children) {
        // TODO Auto-generated method stub
        return "Usage: WxqGenericUDF(String str1, Double d)";
    }



}

     3.由于我们的数据类型要封装成struct,所以先建一张复合数据类型为struct的表:
     这里写图片描述
     4.打包,上传,创建临时函数等步骤同UDF一样。

这里写图片描述

     5.查看表中数据如下:

这里写图片描述

     脚本实现(个人推荐)
      本例采用python,centos自带python,可以通过which python查看,所以不用担心python环境。那么为什么采用python脚本呢?简单啊,编程效率高啊,前面2种方式又得编译又得打包等,麻烦死 。
       1.vim getFee.py,编写python脚本如下:

这里写图片描述

       2.测试脚本,cat py.txt | python getFee.py。注意:这里输入的是本地文件py.txt的内容,实际是把表的查询结果作为输入,所以这里的测试只能表示你写的脚本基本语法和逻辑没问题,不代表查表没问题。这个取决于python脚本的输入。

这里写图片描述

       3.将脚本加入到分布式缓存,add file /home/hadoop/py/getFee.py;

这里写图片描述

       4.查询,select TRANSFORM(name,fee) USING ‘python getFee.py’ as (name,level) from t0415;

这里写图片描述

      5.解析hql
      TRANSFORM(name,fee) :这里面的字段必须为表中字段,是查询结果的输出,python脚本的输入。python中遍历的每行(line)的值就是对应的这俩值,一定要注意这点,我就是刚开始不知道研究了大半天。
      USING ‘python getFee.py’:用哪个脚本来执行。
      as (name,level) :执行结果的表头,对应python中print的字段。

总结:

     本文主要讲了hive中的表,以及开发UDF的3种方式。这些也是日常开发中经常接触到的,比较重要,如果是初学者还是要多加练习和研究。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012415035/article/details/79934188

在Spark中使用UDF对HIVE表进行查询,再将查询结果RDD写入另一个HIVE表

代码如下: package xxx ... import UDF_FUNCTION // udf1 ... object MyObject { case class Recor...
  • shiyanwudi922
  • shiyanwudi922
  • 2015-09-21 09:40:06
  • 1711

Hive的UDF是什么?

首先我们学习hadoop的时候,为了让我们不太会java语言但是对SQL很熟悉的工程师能够操作基本的mapreduce计算过程,Hive被设计出来了。Hive就好比是hadoop在执行MR(mapre...
  • YQlakers
  • YQlakers
  • 2017-04-17 15:18:43
  • 3851

Hive数据仓库--UDF自定义函数以及其中的坑

一个简单的问题折腾了接近半天的时间,不过最终发现了问题出在哪里了,UDF这个是用户自定义函数,和sum等这种函数类似,主要作用是输入一个值,然后通过适当的处理后返回一个值。UDF倒是很简单的,基本上就...
  • wangyang1354
  • wangyang1354
  • 2016-10-31 23:22:57
  • 1773

简单点,搬砖的方式简单点,hive mysql 导入数据的UDF,分享给小伙伴们

我们使用hive一般是执行离线统计分析,然后将执行的结果导入到Mysql的表中供前端报表可视化展现来查询。 导回mysql的方式有许多,以前是用sqoop导回Mysql,还有人用hive jdbc查询...
  • xiao_jun_0820
  • xiao_jun_0820
  • 2016-11-30 11:12:52
  • 1167

09-天亮大数据系列教程之hive之udf/udaf/udtf

目录 1、udf 2、udaf 3、udtf 4、练习题详情 1、udf(user defined function) 背景系统内置函...
  • erliang20088
  • erliang20088
  • 2017-12-01 12:34:56
  • 157

使用Python实现Hive的UDF示例

主要分为两个部分,一个部分为Python脚本实现想要实现的功能,另外一个部分为HQL部分,调用Python脚本对数据进行处理。 HQL调用Python实现的UDF其实有一个重定向的过程,把数据表中之...
  • BabyFish13
  • BabyFish13
  • 2016-12-10 15:49:23
  • 2110

Python实现Hive的UDF

Python实现Hive的UDF
  • u013790563
  • u013790563
  • 2016-06-07 12:19:33
  • 5604

hive udf开发超详细手把手教程

关于hive的udf介绍,就不多啰嗦了。网上的教程一抓一大把,也可以上apache的官网去查阅相关资料,我就省了翻译的时间了。重点给大家带来干货,手把手教会你怎样开发一个udf函数,已经如何部署到服务...
  • bitcarmanlee
  • bitcarmanlee
  • 2016-04-26 11:46:34
  • 23561

编写hive udf和使用hive udf:hue的hive界面中使用hive udf函数、oozie使用hive udf函数、hive命令行使用udf函数

编写hive udf和使用hive udf:hue的hive界面中使用hive udf函数、oozie使用hive udf函数、hive命令行使用udf函数...
  • high2011
  • high2011
  • 2016-09-03 21:20:01
  • 2969

hive分析nginx日志之UDF清洗数据

本文章来自http://www.cnblogs.com/wcwen1990/p/7080300.html hive分析nginx日志一:http://www.cnblogs.com/...
  • qq_35370485
  • qq_35370485
  • 2017-09-12 00:20:09
  • 280
收藏助手
不良信息举报
您举报文章:大数据平台搭建(四):hive中的表及UDF
举报原因:
原因补充:

(最多只允许输入30个字)