8.函数开发

  • Hive支持自定义的第三方库来个性化定制功能,java开发人员可以开发一些用户自定义函数(UDF)、序列号/反序列化器(SerDe)、输入或者输出文件格式或者其他一些增强功能。

修改Log4J属性

  • Hive可以通过conf目录下的2个Log4J配置文件来配置日志。 其中hive-log4j.properties文件来控制CLI和其他本地执行组件的日志 ;而 hive-exec-log4j.properties文件用来控制MapReduce task内的日志 ,这个文件并非必须在Hive安装目录下存在,因为Hive JAR包中已经包含来默认属性值。

  • set hive.root.logger=DEBUG,console修改cli和其他本地组建日志级别

使用Java调试器连接到hive

  • hive --help --debug查看java调试器属性配置

发现和描述函数

  • hive自带的udf,通过show functions可以列举出来当前hive会话中所加载的所有函数名称,其实包括内置和用户加载进来的函数,加载方式。

  • describe function concat,查看函数详细用法。

  • describe function extended concat;显示使用方式

标准函数

  • UDF这个术语在狭义的概念上可以 表示以一行数据中的一列或多列数据作为参数然后返回结果是一个值的函数 。

  • 数据函数round()和floor(),可以将Double转换为bigint类型,round是<=d(最大正整数),floor是>=d(最小正整数)。

聚合函数

  • 聚合函数接受从0行到多行的0个到多个列,然后返回单一值。

  • 聚合函数通常和GROUP BY语句组合使用

select year(ymd),avg(price_close) from stocks 
where exchange='NASDAQ' GROUP year(ymd); 

表生成函数

  • 表生成函数接受0个或多个输入,然后产生多列或多行输出。

    • array函数就是将一列输入转换成一个数组输出。

select array(1,2,3) from dual; 
  • explode()函数以array类型数据作为输入,然后对数组中进行迭代,返回多行结果。explode函数只能单列使用,如果需要查询出来其他列数据可以使用lateral view实现。

select name,ds from test 
lateral view expode(array(2,3,4)) subView AS sub; 

编写UDF

根据生日计算其星座

@Description(name = "custom" 
        , value = "_FUNC_(date)-custom ", 
        extended = "Example:\n select _FUNC_(date_string) from src;") 
public class UDFZodiacSign extends UDF { 
    private SimpleDateFormat sdf; 
    public UDFZodiacSign() { 
        this.sdf = new SimpleDateFormat("yyyy-MM-dd"); 
    } 
    public String evaluate(Date bday) { 
        return this.evaluate(bday.getMonth(), bday.getDay()); 
    } 

    public String evaluate(String bday) { 
        Date date; 
        try { 
            date = sdf.parse(bday); 
        } catch (Exception ex) { 
            return null; 
        } 
        return this.evaluate(date.getMonth() + 1, date.getDay()); 
    } 

    public String evaluate(Integer month, Integer day) { 
        if (month == 1) { 
            if (day < 20) { 
                return "Capricorn"; 
            } else { 
                return "Aquarius"; 
            } 
        } 
        if (month == 5) { 
            if (day < 19) { 
                return "Aquarius"; 
            } else { 
                return "Pisces"; 
            } 
        } 
        /* ...other months here */ 
        return null; 
    } 
} 
  • 添加到hive中,首先需要将jar包放到Hive路径下,然后将加入到分布式缓存中。

add jar xxx.jar
  • 创建临时函数

create temporary function custom AS 'dev.hive.test.udf.UDFZodiacSign'; 
# 查看自动函数 
desc function custom; 
# 使用自定UDF 
select name,bday,custom(bday) from littlebigdata; 
  • 删除临时函数

drop temporary function if exists custom; 

GenericUDF

  • GenericUDF类可以编写一个用户自定义函数nvl(),如果函数传入的值是null,就会返回一个默认值。

不变函数

  • 用户可以通过修改Hive代码重新编译Hive来永久内置自定义的UDF,通过修改FunctionRegistry.java类,如下

“... 
registerUDF("parse_url", UDFParseUrl.class, false); 
registerGenericUDF("nvl", GenericUDFNvl.class); 
registerGenericUDF("split", GenericUDFSplit.class); 
...” 

自定义聚合函数

  • 用户可以定义聚合函数,基于UDAF执行的转换的不同,聚合函数需要在不同阶段的返回类型也可能不一致。例如sum()这个UDAF可以接受基本数据类型的整型输入,然后创建整型部分数据。

使用Collect udaf模拟group_concat

  • 将一组中的所有元素 按照用户指定的分隔符组装成一个字符串 。

  • select concat_ws('d',collect_set(name)) from test2;

  • iterate()和terminatePartial()方法会在map端使用到,terminate()和merge()方法在reduce端使用到,用生成最终结果。

用户自定义表生成函数

产生多行数据的UDTF(自定义表生成函数)

  • explode UDTF可以将数组和map转换为多行

产生具有多个字段的单行数据的UDTF

  • parse_url_tuple:parse_url_tuple(weblogs.url, 'HOST', 'PATH'),URL只需要被解析一次,然后返回多列。

在UDF中访问分布式缓存

  • hive中ADD FILE用于将数据文件加载到分布式缓存中,ADD JAR将Java JAR文件加载到分布式缓存和类路径中。

以函数的方式使用注解

  • 使用UDFType控制

    • deterministic:定数性,如果是不定性的UDF某些优化不能被应用,注入一个特定的输入每次都返回相同的结果,这种确定性只需要保留在查询的上下文中。

    • stateful:状态性 ,几乎所有的UDF默认都是有状态性的,而rand()无状态的,因为每次调用都返回不同的值,stateful适合条件

      • 有状态的UDF只能使用在Select语句后,而不能使用在where、on、order、group后面

      • 当一个查询语句中存在有状态性的UDF时,那么隐含的信息就是Select将会和TRANSFORM进行类似的处理,然后会在对应reducer内部进行,以保证结果是预期的结果。

      • 如果stateful设置为true,是非定性的。

    • runtimeConstant运行时常量:属性被用于标记函数像current_timestamp,current_date,current_datebase()。这些函数不是定性的,但是这些函数返回的值在查询期内应保持一致,因此常量仍然适用于这些功能。

    • 唯一性 distinctLike :一些函数即使输入的列的值是非排重值,其结果也是类似于使用了DISTINCT进行了排重操作,例如min和max函数,

    • 排序性:impliesOrder,使用分析函数指定UDF实现一个排序

    • 交换性:这个操作的结果是否会被其子函数改变

宏命令

  • create temporary macro语法定义

create temporary macro sigmoid(x double)1.0/(1.0+exp(-x)); 
select sigmoid(2) from test limit 1; 

最后更新于