Hive UDF の実行

Prev Next

Classic環境で利用できます。

Hive UDF(User-Defined Functions)はユーザーが作成したコードをHiveクエリ内で実行できるようサポートし、Built-in Functionsだけでは希望するクエリの表現が困難な場合に使用します。
一般に、検索ログ、取引内訳などの特定のフィールドデータに活用するようにUDFを作成して使用します。

関数が受けるInput row、返すOutput row数によって3種類のUDFに区分できます。 各関数の種類ごとに実装するインターフェースが異なります。

  • UDF
    Single rowをInputに受けてSingle rowをOutputに返す関数です。
    ROUND、REPLACEなどのほとんどのMathematical、String FunctionsがUDFタイプに該当します。

  • UDAF
    Multiple rowsをInputに受けてSingle rowをOutputに返す関数です。
    COUNT、MAXなどのAggregate Functionsが該当します。

  • UDTF
    Single rowsをInputに受けてMultiple rows(テーブル)をOuputに返す関数です。
    EXPLODEのような関数が該当します。

このガイドでは、org.apache.hadoop.hive.ql.exec.UDF Hive UDFインターフェースを実装してCloud Hadoopで使用する方法を説明します。

Cloud HadoopでHive UDFを使用するには、以下の手順に従います。

参考

UDFはJavaで実装する必要があり、他のプログラミング言語を使用するにはuser-definedスクリプト(MapReduceスクリプト)を作成してSELECT TRANSFORM構文を使用します。

1. プロジェクトの作成

  1. IntelliJを用いてGradle Projectを作成します。

    • package: com.naverncp.hive

    hadoop-chadoop-use-ex5_1-1_ja

    hadoop-chadoop-use-ex5_1-2_ja

    hadoop-chadoop-use-ex5_1-3_ja

  2. プロジェクトrootの下位のbuild.gradleに以下のようにdependency設定を追加します。

    • 例はCloud Hadoop 1.2にインストールされたコンポーネントと同じバージョンを使用しました。
    plugins {
        id 'java'
    }
    group 'com.naverncp'
    version '1.0-SNAPSHOT'
    sourceCompatibility = 1.8
    repositories {
        mavenCentral()
        maven {
            url "<http://conjars.org/repo>"
        }
    }
    dependencies {
        compile group: 'org.apache.hadoop', name: 'hadoop-client', version: '2.7.3'
        compile group: 'org.apache.hive', name: 'hive-exec', version: '1.2.2'
        compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9'
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }
    

2. インターフェースの実装

  1. 以下の条件を満足するUDFを実装します。

    • UDFはorg.apache.hadoop.hive.ql.exec.UDFを継承する。
    • UDFは少なくとも一つのevaluate()メソッドを実装する。

org.apache.hadoop.hive.ql.exec.UDFインターフェースにevaluate()メソッドは定義されていないため関数がいくつのargumentを受けるかわからず、argumentがどんなタイプなのか前もって知ることはできません。

  // Strip.java
    package com.naverncp.hive;
    import org.apache.commons.lang.StringUtils;
    import org.apache.hadoop.hive.ql.exec.Description;
    import org.apache.hadoop.hive.ql.exec.UDF;
    import org.apache.hadoop.io.Text;
    @Description(
            name = "Strip",
            value = "returns a stripped text",
            extended = "stripping characters from the ends of strings"
    )
    public class Strip extends UDF {
        private Text result = new Text();
        public Text evaluate(Text str){
            if (str == null){
                return null;
            }
            result.set(StringUtils.strip(str.toString()));
            return result;
        }
        public Text evaluate(Text str, String stripChar){
            if (str == null){
                return null;
            }
            result.set(StringUtils.strip(str.toString(), stripChar));
            return result;
        }
    }

上記のクラスでは2つのevaluateメソッドを実装しました。

  • 1番目のメソッド:文字列で前後のスペースを除去
  • 2番目のメソッド:文字列の後ろから指定した文字を除去
  1. UDFをHiveで使用するには、まずJavaクラスを.jarにパッケージングする必要があります。

    • 以下の例は、.jarhdfs:///user/exampleの下にアップロードしたものです。
    $ ./gradlew clean
    $ ./gradlew build
    $ scp -i ~/Downloads/example-home.pem 
    ~/IdeaProjects/hive/build/libs/hive-1.0-SNAPSHOT.jar sshuser@pub-
    4rrsj.hadoop.ntruss.com:~/
    $ ssh -i ~/Downloads/example-home.pem  sshuser@pub-
    4rrsj.hadoop.ntruss.com
    
    [sshuser@e-001-example-0917-hd ~]$ hadoop fs -copyFromLocal hive-1.0-SNAPSHOT.jar /user/example/
    

3. Hiveを使用する

  1. 以下のコマンドを使用して任意のhive tableを1つ作成します。

    [sshuser@e-001-example-0917-hd ~]$ echo 'dummy' > /tmp/dummy.txt
    [sshuser@e-001-example-0917-hd ~]$ hive -e "CREATE TABLE dummy (value STRING); \\
    LOAD DATA LOCAL INPATH '/tmp/dummy.txt' \\
    OVERWRITE INTO TABLE dummy"
    
  2. 以下のコマンドを使用してHive CLIを実行します。

    • エッジノードにHiveServerがインストールされているため、別途のオプションは不要です。
    [sshuser@e-001-example-0917-hd ~]$ hive
    20/11/06 16:04:39 WARN conf.HiveConf: HiveConf of name hive.server2.enable.doAs.property does not exist
    log4j:WARN No such property [maxFileSize] in org.apache.log4j.DailyRollingFileAppender.
    
    Logging initialized using configuration in file:/etc/hive/2.6.5.0-292/0/hive-log4j.properties
    hive>
    
  3. 以下のようにmetastoreで関数を登録します。

    • CREATE FUNCTION構文で名前を設定します。
    • Hive Metastore:テーブルとパーティションに関連したメタ情報を保存する場所
    hive> CREATE FUNCTION strip AS 'com.naverncp.hive.Strip'
        > USING JAR 'hdfs:///user/example/hive-1.0-SNAPSHOT.jar';
    converting to local hdfs:///user/example/hive-1.0-SNAPSHOT.jar
    Added [/tmp/99c3d137-f58e-4fab-8a2a-98361e3e59a1_resources/hive-1.0-SNAPSHOT.jar] to class path
    Added resources: [hdfs:///user/example/hive-1.0-SNAPSHOT.jar]
    OK
    Time taken: 17.786 seconds
    

    または、metastoreに関数を永続的に保存せずにHiveセッション中のみ使用するには、以下のようにTEMPORARY keywordを使用します。

    ADD JAR 'hdfs:///user/example';
    CREATE TEMPORARY FUNCTION strip AS 'com.naverncp.hive.Strip'
    
  4. ビルドしたstrip関数が正常に実行されるのかを確認します。 空白が除去されたことが確認できます。

    hive> select strip('  bee  ') from dummy;
    converting to local hdfs:///user/example/hive-1.0-SNAPSHOT.jar
    Added [/tmp/70e2e17a-ecca-41ff-9fe6-48417b8ef797_resources/hive-1.0-SNAPSHOT.jar] to class path
    Added resources: [hdfs:///user/example/hive-1.0-SNAPSHOT.jar]
    OK
    bee
    Time taken: 0.967 seconds, Fetched: 1 row(s)
    hive> select strip('banana', 'ab') from dummy ;
    OK
    nan
    Time taken: 0.173 seconds, Fetched: 1 row(s)
    

関数の削除は、以下のように実行できます。

DROP FUNCTION strip
参考

データの特性に応じてよく使うロジックをUDFに作成しておくと、SQL構文で簡単にデータを照会できます。