Hive学习笔记06

目录

8.6 自定义函数

8.7 自定义UDF函数

9、分区表和分桶表

9.1 分区表

9.1.1 分区表基本语法

9.1.2 二级分区表

9.1.3 动态分区

9.2 分桶表

9.2.1 分桶表基本语法

9.2.2 分桶排序表


8.6 自定义函数

1)Hive自带了一些函数比如:max/min但是数量有限自己可以通过自定义UDF来方便的扩展。

2)Hive提供的内置函数无法满足你的业务处理需要时此时就可以考虑使用用户自定义函数(UDF:user-defined function)

3)根据用户自定义函数类别分为以下三种:

(1)UDF(User-Defined-Function)

一进一出。

(2)UDAF(User-Defined Aggregation Function)

用户自定义聚合函数,多进一出。

类似于:count/max/min

(3)UDTF(User-Defined Table-Generating Functions)

用户自定义表生成函数,一进多出。

lateral view explode()

4)编程步骤

(1)继承Hive提供的类

org.apache.hadoop.hive.ql.udf.generic.GenericUDF

org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;

(2)实现类中的抽象方法

(3)在hive的命令行窗口创建函数

添加jar。

add jar linux_jar_path

创建function。

create [temporary] function [dbname.]function_name AS class_name;

(4)在hive的命令行窗口删除函数

drop [temporary] function [if exists] [dbname.]function_name;

8.7 自定义UDF函数

0)需求

自定义一个UDF实现计算给定基本数据类型的长度,例如:

hive(default)> select my_len("abcd");

4

1创建一个Maven工程Hive

2)导入依赖

<dependencies>

<dependency>

<groupId>org.apache.hive</groupId>

<artifactId>hive-exec</artifactId>

<version>3.1.3</version>

</dependency>

</dependencies>

3创建一个类

package com.atguigu.hive.udf;



import org.apache.hadoop.hive.ql.exec.UDFArgumentException;

import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;

import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;

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.primitive.PrimitiveObjectInspectorFactory;



/**

 * 我们需计算一个要给定基本数据类型的长度

 */

public class MyUDF extends GenericUDF {

    /**

     * 判断传进来的参数的类型和长度

     * 约定返回的数据类型

     */

    @Override

    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {



        if (arguments.length !=1) {

            throw  new UDFArgumentLengthException("please give me  only one arg");

        }



        if (!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)){

            throw  new UDFArgumentTypeException(1, "i need primitive type arg");

        }



        return PrimitiveObjectInspectorFactory.javaIntObjectInspector;

    }



    /**

     * 解决具体逻辑的

     */

    @Override

    public Object evaluate(DeferredObject[] arguments) throws HiveException {



        Object o = arguments[0].get();

        if(o==null){

            return 0;

        }



        return o.toString().length();

    }



    @Override

    // 用于获取解释的字符串

    public String getDisplayString(String[] children) {

        return "";

    }

}

4创建临时函数

(1)打成jar包上传到服务器/opt/module/hive/datas/myudf.jar

(2)将jar包添加到hive的classpath,临时生效

hive (default)> add jar /opt/module/hive/datas/myudf.jar;

(3)创建临时函数与开发好的java class关联

hive (default)>

create temporary function my_len

as "com.atguigu.hive.udf.MyUDF";

(4)即可在hql中使用自定义的临时函数

hive (default)>

select

    ename,

    my_len(ename) ename_len

from emp;

(5)删除临时函数

hive (default)> drop temporary function my_len;

注意:临时函数只跟会话有关系,跟库没有关系。只要创建临时函数的会话不断,在当前会话下,任意一个库都可以使用其他会话全都不能使用。

  1. 创建永久函数

(1)创建永久函数

注意:因为add jar本身也是临时生效,所以在创建永久函数的时候,需要制定路径(并且因为元数据的原因,这个路径还得是HDFS上的路径)。

hive (default)>

create function my_len2

as "com.atguigu.hive.udf.MyUDF"

using jar "hdfs://hadoop102:8020/udf/myudf.jar";

(2)即可在hql中使用自定义的永久函数 

hive (default)>

select

    ename,

    my_len2(ename) ename_len

from emp;

(3)删除永久函数 

hive (default)> drop function my_len2;

注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。

永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。

永久函数使用的时候,需要在指定的库里面操作,或者在其他库里面使用的话加上,库名.函数名。

9、分区表和分桶表

9.1 分区表

Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多。

9.1.1 分区表基本语法

1. 创建分区表

hive (default)>

create table dept_partition

(

    deptno int,    --部门编号

    dname  string, --部门名称

    loc    string  --部门位置

)

    partitioned by (day string)

    row format delimited fields terminated by '\t';

2. 分区表读写数据

1)写数据

(1)load

1数据准备

在/opt/module/hive/datas/路径上创建文件dept_20220401.log,并输入如下内容。

[atguigu@hadoop102 datas]$ vim dept_20220401.log

10 行政部 1700

20 财务部 1800

2装载语句

hive (default)>

load data local inpath '/opt/module/hive/datas/dept_20220401.log'

into table dept_partition

partition(day='20220401');

(2)insert

day='20220401'分区的数据插入到day='20220402'分区,可执行如下装载语句

hive (default)>

insert overwrite table dept_partition partition (day = '20220402')

select deptno, dname, loc

from dept_partition

where day = '2020-04-01';

2)读数据

查询分区表数据时,可以将分区字段看作表的伪列,可像使用其他字段一样使用分区字段。

select deptno, dname, loc ,day

from dept_partition

where day = '2020-04-01';

3. 分区表基本操作

1)查看所有分区信息

hive> show partitions dept_partition;

2)增加分区

1创建单个分区

hive (default)>

alter table dept_partition

add partition(day='20220403');

2)同时创建多个分区(分区之间不能有逗号)

hive (default)>

alter table dept_partition

add partition(day='20220404') partition(day='20220405');

3)删除分区

1)删除单个分区

hive (default)>

alter table dept_partition

drop partition (day='20220403');

2)同时删除多个分区(分区之间必须有逗号)

hive (default)>

alter table dept_partition

drop partition (day='20220404'), partition(day='20220405');

4)修复分区

Hive将分区表的所有分区信息都保存在了元数据中,只有元数据与HDFS上的分区路径一致时,分区表才能正常读写数据。若用户手动创建/删除分区路径,Hive都是感知不到的,这样就会导致Hive的元数据和HDFS的分区路径不一致。再比如,若分区表为外部表,用户执行drop partition命令后,分区元数据会被删除,而HDFS的分区路径不会被删除,同样会导致Hive的元数据和HDFS的分区路径不一致。

若出现元数据和HDFS路径不一致的情况,可通过如下几种手段进行修复。

(1)add partition

若手动创建HDFS的分区路径,Hive无法识别,可通过add partition命令增加分区元数据信息,从而使元数据和分区路径保持一致。

2)drop partition

若手动删除HDFS的分区路径,Hive无法识别,可通过drop partition命令删除分区元数据信息,从而使元数据和分区路径保持一致。

(3)msck

若分区元数据和HDFS的分区路径不一致,还可使用msck命令进行修复,以下是该命令的用法说明。

hive (default)>

msck repair table table_name [add/drop/sync partitions];

说明:

- msck repair table table_name add partitions:该命令会增加HDFS路径存在但元数据缺失的分区信息。

- msck repair table table_name drop partitions:该命令会删除HDFS路径已经删除但元数据仍然存在的分区信息。

- msck repair table table_name sync partitions:该命令会同步HDFS路径和元数据分区信息,相当于同时执行上述的两个命令。

msck repair table table_name:等价于msck repair table table_name add partitions命令。

9.1.2 二级分区表

思考:如果一天内的日志数据量也很大,如何再将数据拆分?

答案是二级分区表,例如可以在按天分区的基础上,再对每天的数据按小时进行分区。

1)二级分区表建表语句

hive (default)>

create table dept_partition2(

    deptno int,    -- 部门编号

    dname string, -- 部门名称

    loc string     -- 部门位置

)

partitioned by (day string, hour string)

row format delimited fields terminated by '\t';

2)数据装载语句

hive (default)>

load data local inpath '/opt/module/hive/datas/dept_20220401.log'

into table dept_partition2 

partition(day='20220401', hour='12');

3查询分区数据

hive (default)>

select

    *

from dept_partition2

where day='20220401' and hour='12';

9.1.3 动态分区

动态分区是指向分区表insert数据时,被写往的分区不由用户指定,而是由每行数据的最后一个字段的值来动态的决定。使用动态分区,可只用一个insert语句将数据写入多个分区。

1)动态分区相关参数

(1)动态分区功能总开关(默认true,开启)

set hive.exec.dynamic.partition=true

(2)严格模式和非严格模式

动态分区的模式,默认strict(严格模式),要求必须指定至少一个分区为静态分区,nonstrict(非严格模式)允许所有的分区字段都使用动态分区。

set hive.exec.dynamic.partition.mode=nonstrict

(3)一条insert语句可同时创建的最大的分区个数,默认为1000。

set hive.exec.max.dynamic.partitions=1000

(4)单个Mapper或者Reducer可同时创建的最大的分区个数,默认为100。

set hive.exec.max.dynamic.partitions.pernode=100

(5)一条insert语句可以创建的最大的文件个数,默认100000。

hive.exec.max.created.files=100000

(6)当查询结果为空时且进行动态分区时,是否抛出异常,默认false。

hive.error.on.empty.partition=false

2)案例实操

需求:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition_dynamic的相应分区中。

(1)创建目标分区表

hive (default)>

create table dept_partition_dynamic(

    id int,

    name string

)

partitioned by (loc int)

row format delimited fields terminated by '\t';

(2)设置动态分区

set hive.exec.dynamic.partition.mode = nonstrict;

hive (default)>

insert into table dept_partition_dynamic

partition(loc)

select

    deptno,

    dname,

    loc

from dept;

(3)查看目标分区表的分区情况

hive (default)> show partitions dept_partition_dynamic;

9.2 分桶表

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围划分,分区针对的是数据的存储路径,分桶针对的是数据文件。

分桶表的基本原理是,首先为每行数据计算一个指定字段的数据的hash值,然后模以一个指定的分桶数,最后将取模运算结果相同的行,写入同一个文件中,这个文件就称为一个分桶(bucket)。

9.2.1 分桶表基本语法

1)建表语句

hive (default)>

create table stu_buck(

    id int,

    name string

)

clustered by(id)

into 4 buckets

row format delimited fields terminated by '\t';

2)数据装载

(1)数据准备

在/opt/module/hive/datas/路径上创建student.txt文件,并输入如下内容。

1001 student1

1002 student2

1003 student3

1004 student4

1005 student5

1006 student6

1007 student7

1008 student8

1009 student9

1010 student10

1011 student11

1012 student12

1013 student13

1014 student14

1015 student15

1016 student16

(2)导入数据到分桶表中

说明:Hive新版本load数据可以直接MapReduce,老版的Hive需要将数据传到一张表里,再通过查询的方式导入到分桶表里面。

hive (default)>

load data local inpath '/opt/module/hive/datas/student.txt'

into table stu_buck;

(3)查看创建的分桶表中是否分成4个桶

(4)观察每个分桶中的数据

9.2.2 分桶排序表

1)建表语句

hive (default)>

create table stu_buck_sort(

    id int,

    name string

)

clustered by(id) sorted by(id)

into 4 buckets

row format delimited fields terminated by '\t';

2)数据装载

(1)导入数据到分桶表中

hive (default)>

load data local inpath '/opt/module/hive/datas/student.txt'

into table stu_buck_sort;

(2)查看创建的分桶表中是否分成4个桶

(3)观察每个分桶中的数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值