1. 程式人生 > >Hive函數以及自定義函數講解(UDF)

Hive函數以及自定義函數講解(UDF)

ora scope for aps log linu reg 查看 uil

Hive函數介紹
HQL內嵌函數只有195個函數(包括操作符,使用命令show functions查看),基本能夠勝任基本的hive開發,但是當有較為復雜的需求的時候,可能需要進行定制的HQL函數開發。HQL支持三種方式來進行功能的擴展(只支持使用java編寫實現自定義函數),分別是:UDF(User-Defined Function)、UDAF(User-Defined Aggregate Function)和UDTF(User-Defined Table-Generating Function)。當我們使用java語言進行開發完成後,將生成的jar包移到linux機器(hive機器)上,進行函數的創建,然後進行使用即可。

技術分享圖片


函數創建命令
HQL函數的創建一般分為以下幾步:


1. 添加jar(0.13.*不支持hdfs上的jar添加,14版本才開始支持)
add jar linux_jar_path

add jar /home/hadoop/bigdatasoftware/datas/hive-1.0-SNAPSHOT.jar

技術分享圖片


2. 創建function,語法規則如下:
create [temporary] function [dbname.]function_name AS class_name;

create temporary function myfuntion as ‘com.gec.demo.LowerUDF‘;

技術分享圖片


3. 使用function,和使用其他函數一樣。

技術分享圖片



函數刪除命令
我們可以通過drop命令刪除自定義函數,語法規則如下:


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

技術分享圖片



自定義UDF介紹
UDF(User-Defined Function)支持一個輸入產生一個輸出,是一個最常用的自定義函數類型。實現自定義UDF要求繼承類org.apache.hadoop.hive.ql.exec.UDF,並且在自定義UDF類中重載實現evaluate方法,我們可以通過重載多個evaluate方法達到函數參數多樣化的需求。


實現案例:實現一個大小寫轉換的函數,要求函數通過參數的不同決定是進行那種轉換,默認是轉換為小寫。
UDAF介紹
UDAF(User-Defined Aggregate Function)支持多個輸入,一個輸出。在原來的版本中可以通過繼承UDAF類來實現自定義UDAF,但是現在hive已經將這個類標註為棄用狀態。現在一般通過繼承AbstractGenericUDAFResolver類來實現自定義UDAF,通過這種方式要求實現自定義的GenericUDAFEvaluator。也就是說在現在的hive版本中,實現自定義UDAF,那麽需要實現兩個類,分別是AbstractGenericUDAFResolver和GenericUDAFEvaluator。
AbstractGenericUDAFResolver介紹
AbstractGenericUDAFResolver類主要作用就是根據hql調用時候的函數參數來獲取具體的GenericUDAFEvaluator實例對象,也就是說實現方法getEvaluator即可,該方法的主要作用就是根據參數的不同返回不同的evaluator實例對象,實現多態性。

maven依賴配置如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>BigdataStudy</artifactId>
        <groupId>com.gec.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hive</artifactId>

    <name>hive</name>
    <!-- FIXME change it to the project‘s website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <hadoop.version>2.7.2</hadoop.version>
        <!--<hive.version> 0.13.1</hive.version>-->
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-jdbc</artifactId>
        <version>0.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>0.13.1</version>
        </dependency>


    </dependencies>
</project>

自定義的函數如下:

package com.gec.demo;

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

public class LowerUDF extends UDF {
    public Text evaluate(Text str){
        if (null==str.toString()){
            return null;
        }
        return new Text(str.toString().toLowerCase());
    }

    public static void main(String[] args) {
        System.out.println(new LowerUDF().evaluate(new Text("HIVE")));
    }

}

然後打包jar包,

技術分享圖片

將jar包發送到Linux的/home/hadoop/bigdatasoftware/datas目錄下


GenericUDAFEvaluator介紹
GenericUDAFEvaluator類主要作用就是根據job的不同階段執行不同的方法。hive通過GenericUDAFEvaluator.Model來確定job的執行階段。PARTIAL1:從原始數據到部分聚合,會調用方法iterate和terminatePartial方法;PARTIAL2:從部分數據聚合和部分數據聚合,會調用方法merge和terminatePartial;FINAL:從部分數據聚合到全部數據聚合,會調用方法merge和terminate;COMPLETE:從原始數據到全部數據聚合,會調用方法iterate和terminate。除了上面提到的iterate、merge、terminate和terminatePartial以外,還有init(初始化並返回返回值的類型)、getNewAggregationBuffer(獲取新的buffer對象,也就是方法之間傳遞參數的對象),reset(重置buffer對象)。
UDTF介紹
UDTF(User-Defined Table-Generating Function)支持一個輸入多個輸出。一般用於解析工作,比如說解析url,然後獲取url中的信息。要求繼承類org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,實現方法:initialize(返回返回值的參數類型)、process具體的處理方法,一般在這個方法中會調用父類的forward方法進行數據的寫出、close關閉資源方法,最終會調用close方法,同MR程序中的cleanUp方法。
實現功能:解析爬蟲數據,從數據中讀取產品id、產品名稱、價格。

常用的三種集成自定義函數的方式
首先要求創建的function是永久function,不能是臨時function。
第一種:修改hive-site.xml文件,添加參數hive.aux.jars.path,value為jar包的linux本地路徑,要求是以file:///開頭的絕對路徑。
第二種:直接將jar包移動到hive的lib文件夾中。
第三種:將jar包移動到hdfs上,然後在創建function的時候指定function使用的hdfs上的jar文件絕對路徑(包括hdfs://hh:8020/前綴),這樣在使用的時候,hive會自動將jar下載到本地進行緩存的。

Hive函數以及自定義函數講解(UDF)