- 인쇄
- PDF
Hive UDF 실행
- 인쇄
- PDF
Hive UDF(User-Defined Functions)는 사용자가 작성한 코드를 Hive 쿼리 내에서 실행할 수 있게 도와주며, Built-in Functions만으로는 원하는 쿼리를 표현하기 어려울 때 사용합니다.
보통 검색 로그, 거래 내역 등 특정 필드 데이터에 활용할 수 있도록 UDF를 작성하여 사용합니다.
함수가 받는 Input row, 반환하는 Output row 수에 따라 세 가지 종류의 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 스크립트(MapReduce 스크립트)를 만든 후, SELECT TRANSFORM 구문을 사용해 주십시오.
1. 프로젝트 생성
IntelliJ를 사용해 Gradle Project를 생성해 주십시오.
- package:
com.naverncp.hive
- package:
프로젝트 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. 인터페이스 구현
다음 조건을 만족하는 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; } }
- UDF는
위의 클래스에서는 두 개의 evaluate
메소드를 구현하였습니다.
- 첫 번째 메소드: 문자열에서 앞, 뒤 공백 제거
- 두 번째 메소드: 문자열 뒤에서부터 지정한 문자 제거
UDF를 Hive에서 사용하려면 먼저 Java 클래스를
.jar
로 패키징해 주십시오.- 다음 예시는
.jar
를hdfs:///user/suewoon
아래에 업로드한 것입니다.
$ ./gradlew clean $ ./gradlew build $ scp -i ~/Downloads/example-home.pem ~/IdeaProjects/hive/build/libs/hive-1.0-SNAPSHOT.jar sshuser@pub- 4rrsj.hadoop.fin-ntruss.com:~/ $ ssh -i ~/Downloads/example-home.pem sshuser@pub- 4rrsj.hadoop.fin-ntruss.com [sshuser@e-001-example-0917-hd ~]$ hadoop fs -copyFromLocal hive-1.0-SNAPSHOT.jar /user/example/
- 다음 예시는
3. Hive 사용
다음 명령어를 사용하여 임의의
hive table
을 하나 생성해 주십시오.[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"
다음 명령어를 사용하여 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>
아래와 같이
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'
빌드한
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 구문으로 쉽게 데이터를 조회할 수 있습니다.