Hive UDF 실행
  • PDF

Hive UDF 실행

  • PDF

Hive는 사용자가 작성한 Processing 코드를 붙여 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(table)를 Ouput으로 반환하는 함수입니다.
    EXPLODE 같은 함수가 해당합니다.

이 가이드에서는 org.apache.hadoop.hive.ql.exec.UDF Hive UDF 인터페이스를 구현하여 Cloud Hadoop에서 사용하는 방법을 설명합니다.

Cloud Hadoop에서 Hive UDF를 사용하기 위해 다음 단계를 차례대로 진행해 주십시오.

참고

UDF는 Java로 구현해야 하며 다른 프로그래밍 언어를 사용하려면 user-defined script(MapReduce script)를 만들어 SELECT TRANSFORM 구문을 사용해 주십시오.

1. 프로젝트 생성

  1. IntelliJ를 사용해 Gradle Project를 생성해 주십시오.

    • package: com.naverncp.hive

    hadoop-chadoop-use-ex5_1-1_ko

    hadoop-chadoop-use-ex5_1-2_ko

    hadoop-chadoop-use-ex5_1-3_ko

  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() 메소드를 구현한다.

    함수가 몇 개의 argument를 받게 될지, argument가 어떤 타입일지 미리 알기 어려워 org.apache.hadoop.hive.ql.exec.UDF 인터페이스에 evaluate() 메소드가 정의되어 있지 않기 때문입니다.

    // 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;
        }
    }
    

위의 클래스에서는 두 개의 evaluate 메소드를 구현하였습니다.

  • 첫 번째 메소드: 문자열에서 앞, 뒤 공백 제거
  • 두 번째 메소드: 문자열 뒤에서부터, 지정한 문자 제거
  1. UDF를 hive에서 사용하려면 먼저 java class를 .jar로 패키징해 주십시오.

    • 다음 예시는 .jarhdfs:///user/suewoon 아래에 업로드한 것입니다.
    $ ./gradlew clean
    $ ./gradlew build
    $ scp -i ~/Downloads/suewoon-home.pem 
    ~/IdeaProjects/hive/build/libs/hive-1.0-SNAPSHOT.jar sshuser@pub-
    4rrsj.hadoop.ntruss.com:~/
    $ ssh -i ~/Downloads/suewoon-home.pem  sshuser@pub-
    4rrsj.hadoop.ntruss.com
    
    [sshuser@e-001-suewoon-0917-hd ~]$ hadoop fs -copyFromLocal hive-1.0-SNAPSHOT.jar /user/suewoon/
    

3. Hive 사용

  1. 다음 명령어를 사용하여 임의의 hive table을 하나 생성해 주십시오.

    [sshuser@e-001-suewoon-0917-hd ~]$ echo 'dummy' > /tmp/dummy.txt
    [sshuser@e-001-suewoon-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-suewoon-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/suewoon/hive-1.0-SNAPSHOT.jar';
    converting to local hdfs:///user/suewoon/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/suewoon/hive-1.0-SNAPSHOT.jar]
    OK
    Time taken: 17.786 seconds
    

    또는 metastore에 함수를 영구적으로 저장하지 않고 hive session 동안에만 사용하려면 아래와 같이 TEMPORARY keyword를 사용해 주십시오.

    ADD JAR 'hdfs:///user/suewoon';
    CREATE TEMPORARY FUNCTION strip AS 'com.naverncp.hive.Strip'
    
  4. 빌드한 strip 함수가 제대로 수행되는지 확인해 주십시오. 공백이 제거된 것을 확인할 수 있습니다.

    hive> select strip('  bee  ') from dummy;
    converting to local hdfs:///user/suewoon/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/suewoon/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 구문으로 쉽게 데이터를 조회할 수 있습니다.


이 글이 도움이 되었나요?