CloudHadoop에서 Hive UDF 실행하기
By: Suewoon Ryu
Tags: Hadoop, Hive, Naver Cloud Platform, Cloud Computing, Database

프로젝트 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'

}

구현하기

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 메소드를 구현하였습니다.

첫번째 메소드 - 문자열에서 앞, 뒤 공백을 제거합니다.

두번째 메소드 - 문자열 뒤에서 부터, 지정한 문자를 제거합니다.

이 UDF를 hive에서 사용하려면 먼저 java class를 .jar 로 패키징 해야 합니다. 이 .jar를 hdfs:///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/

사용하기

먼저 임의로 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"

아래 처럼 Hive CLI 를 시작합니다. edge노드에 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>

아래와 같이 metastore에서 함수를 등록하면 됩니다. CREATE FUNCTION 구문으로 이름을 설정합니다.

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'

빌드한 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

마치며

이번 페이지에서는 Hive UDF를 빌드하여 Cloud Hadoop에서 사용하는 방법을 알아봤습니다. 데이터의 특성에 따라, 자주 쓰게 되는 로직을 UDF로 만들어 두면 쉽게 SQL 구문으로 데이터를 조회 할 수 있습니다.