SlideShare a Scribd company logo
1 of 19
Download to read offline
RHive 튜토리얼 4 - UDF, UDAF, UDTF 함수

RHive - advanced functions
RHive는 기초함수(basic functions), HDFS, map/reduce를 위한 apply 계열, 그리고
UDF, UDAF, UDTF를 지원하기 위한 고급 함수들을 지원한다.
Advanced function들은 Hive의 UDF와 UDAF를 R로 구현하여 적용하는데 필요한
UDF/UDAF 함수들로 구성되어 있다.
이 함수들을 활용하면 매우 낮은 복잡한 수준까지 R을 적용하여 Hadoop과 Hive를
이용한 Map/Reduce 프로그래밍을 할 수 있으며
Data mining의 복잡한 알고리즘이나 데이터 프로세싱도 많은 부분을 R언어를
이용해서 처리할 수 있다.


RHive - UDF and UDAF functions
Hive는 UDF(User Defined Function), UDAF(User Defined Aggregate Function),
UDTF(User Defined Table create Function)을 제공한다.
UDF는 count, avg, min, max와 같은 SQL구문으로 한 컬럼 또는 여러 컬럼에 대해
연산을 수행하는 Hive의 내장된 function을 말한다.
Hive는 기본적으로 몇개의 UDF를 지원하며 사용자가 개발하여 추가할 수 있다.
하지만 원래 Hive에서의 UDF, UDAF, UDTF는 모두 Java로 작성되어야 하며 R언어를
직접 사용할 수 없다.
RHive는 UDF와 UDAF를 R언어로 작성하고 Hive에서 수행할 수 있게 기능을 지원한다.
또 RHive가 미리 작성해 둔 UDTF를 활용하여 복잡한 컬럼 분해 작업을 가능하게 해준다.
이 튜토리얼에서는 UDF와 UDAF작성할 때 사용하는 함수들과 예제를 통해 이것들을
어떻게 구현하고 적용하는지를 설명한다.


rhive.assign

rhive.assign 함수는 R에서 작성된 함수들과 생성한 변수들을 Hive에서 참조할 수 있게
지정하는 역할을 한다.
이같은 assign이 과정이 필요한 이유는 R에서 작성한 코드와 벡터, 매트릭스,
데이터프레임, 펑션들 중
어느 것이 분산환경에서 사용될 것인지 지정(assign)해 주는 작업이 필요하기 때문이다.
rhive.assign이 바로 분산환경으로 내보내기 위한 함수와 변수, 객체들을 지정하는 일을
한다.
주의할 점은 rhive.assign는 분산환경으로 함수와 변수, 객체들을 배포하기 전에 필요한
작업들을 수행하지만 실제로 분산환경에서 배포하지는 않는다.
단지 준비를 위한 것으로 실제로 배포작업을 해주는 rhive.export나 rhive.exporlAll과
같은 펑션들과 연달아 쓰이는 것이 일반적이다.
배포의 의미는 Hadoop의 Map/Reduce처럼 Hive에서 사용될 함수와 객체들을
Hadoop의 Job node에 미리 대기시켜 두었다가
데이터를 처리할 때 불러 쓰기 위한 준비과정으로 생각하면 된다.
rhive.assign 함수는 인수(argument)를 2개 입력받으며
첫번째는 R에서 생성한 심볼의 character type의 alias이며 두 번째는 배포할 심볼
자체이다.
만약 분산환경에 전달할 심볼이 newsum이라는 이름을 가지고 있다면
rhive.assign을 사용하여 다음과 같이 지정해준다.

newsum	
  <-­‐	
  function(value)	
  {	
  
	
  	
  value	
  +	
  1	
  
}	
  
rhive.assign("newsum",	
  newsum)

구문이 다소 어색해 보일 수는 있지만 이것은 R의 구조로 인한 문제로 향후 버전에서
개선될 것이다.
첫번째 인수에는 두번째 인수로 들어갈 심볼을 문자열로 만들어주기만 하면 된다.
보통은 심볼의 이름과 같은 문자열을 넣어주는 것이 작업하는데 편리하며
심볼가 동일 하지 않은 다른 문자열을 주어도 상관없지만
이름을 바꾸는 경우 실제 사용할때는 지정한 심볼의 이름이 바뀌는 것을 주의해야 하고
혼동하기 쉬우므로 바꾸지 않는 것이 좋다.
다음에 나오는 예를 통해 rhive.assign을 사용하는 방법을 살펴보자.
다음 사용예는 sum3values라는 function 만들고 rhive.assign을 이용해서 분산환경에
배포될 것들을 정의한 예이다.

sum3values	
  <-­‐	
  function(a,b,c)	
  {	
  
	
  	
  a	
  +	
  b	
  +	
  c	
  
}	
  
 	
  
rhive.assign("sum3values",	
  sum3values)	
  
[1]	
  TRUE

아래와 같이 함수가 아닌 객체를 지정할 수도 있다.

coef1	
  <-­‐	
  3.141593	
  
rhive.assign("coef1",	
  coef1)

데이터프레임을 비롯한 어떤 것도 가능하다.

library(MASS)	
  
>	
  head(cats)	
  
	
  	
  Sex	
  Bwt	
  Hwt	
  
1	
  	
  	
  F	
  2.0	
  7.0	
  
2	
  	
  	
  F	
  2.0	
  7.4	
  
3	
  	
  	
  F	
  2.0	
  9.5	
  
4	
  	
  	
  F	
  2.1	
  7.2	
  
5	
  	
  	
  F	
  2.1	
  7.3	
  
6	
  	
  	
  F	
  2.1	
  7.6	
  
>	
  rhive.assign("cats",	
  cats)	
  
[1]	
  TRUE

객체와 dataframe등은 분산환경에 배포해서 기존에 만들어둔 값이나 coefficient등을
참조해서 연산하는데 이용할 수 있다.
다만 이런 객체들이 분산환경으로 배포되면 분산환경내에서는 공유메모리(shared
memory)와 같은 개념이 아니고
단지 local memory에 존재하는 것들이므로 주의해야 한다.


rhive.export
rhive.export는 R에서 만들어진 객체들을 분산환경에 실제로 배포해서 분산환경에서
실행되도록 준비하는 것을 처리해 준다.
rhive.export는 rhive.assign과 함께 사용되며 rhive.export의 인수로 주는 객체의
이름들은 반드시 rhive.assign으로 배포준비가 끝난 것이어야 한다.
다음의 예를 통해서 사용법을 쉽게 알 수 있다.
sum3values	
  <-­‐	
  function(a,b,c)	
  {	
  
  	
  	
  a	
  +	
  b	
  +	
  c	
  
  }	
  
  	
  	
  
  rhive.assign("sum3values",	
  sum3values)	
  
  	
  	
  
  rhive.export(sum3values)

rhive.export는 첫번째 인수(argument)인 exportname을 제외하고도 많은 인수를
가지고 있다.
하지만 이런 것들은 복잡하게 구성된 환경에서 사용될 수 있도록
배포할 서버와 port등을 별도로 지정할 수 있게 해 둔 것으로
보통의 경우에는 사용할 필요가 없다.
이런것들을 사용해야 할 만큼 RHive를 복잡한 환경에 구성해야 한다면 매뉴얼을
참조하거나 RHive 개발팀에 문의하도록 한다.


rhive.exportAll
rhive.exportAll 함수느 rhive.export와 기능상으로 동일한 함수이지만
다른점은 rhive.exportAll은 인수로 넘겨준 문자열로 시작하는 심볼을 모두 한꺼번에
넘겨주는 역할을 한다.
이 함수는 주로 R로 작성된 UDAF function을 배포하기 위한 용도로 사용된다.
R로 작성된 UDAF 펑션은 같은 이름으로 시작하는 4개 펑션으로 구성되어야 하는
제약이 있으며 이것들을 쉽게 배포하기 위해 만들어둔 일종의 rhive.export를 변형한
함수이다.
다음의 예는 4개의 함수를 만들고 이것들을 분산환경의 RHive 서버로 배포하는 작업을
한다.

sumAllColumns	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  	
  	
  }	
  
	
  	
  
	
  	
  	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.partial	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
sumAllColumns.merge	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.terminate	
  <-­‐	
  function(values)	
  {	
  
	
  	
  	
  	
  values	
  
}	
  
	
  	
  
rhive.assign("sumAllColumns",	
  sumAllColumns)	
  
rhive.assign("sumAllColumns.partial",	
  sumAllColumns.partial)	
  
rhive.assign("sumAllColumns.merge",	
  sumAllColumns.merge)	
  
rhive.assign("sumAllColumns.terminate",	
  sumAllColumns.terminate)	
  
	
  	
  
rhive.exportAll("sumAllColumns")	
  

실제로 위에서 마지막줄은 다음과 동일하다.

#	
  rhive.exportAll("sumAllColumns")	
  
	
  	
  
rhive.export("sumAllColumns")	
  
rhive.export("sumAllColumns.partial")	
  
rhive.export("sumAllColumns.merge")	
  
rhive.export("sumAllColumns.terminate")

rhive.assign과 rhive.export, rhive.exportAll은 R에서 생성한 펑션과 객체들을
분산환경에서 가동중인 Rserve로 전달하여 Hive와 Hadoop이 사용할 수 있도록
준비하는 작업까지만 수행한다.
이렇게 배포한 R 펑션과 객체들을 실제로 사용하기 위해서는 rhive.query에 전달하는
SQL구문에 기술해야만 사용할 수 있다.
다음에 나오는 예제들을 통해 배포한 함수들을 어떻게 작동시키는지 배우게 될 것이다.


RHive - UDF usage
이제 UDF를 적용해 볼 테이블을 하나 준비해야 한다.
Hive에 UDF를 테스트해 볼 적당한 테이블이 없다면 테이블을 하나 만든다.
이 튜토리얼에서는 USArrests라는 data를 Hive 테이블로 변환할 것이다.
USArrests는 R이 원래 가지고 있는 작은 데이터이다.
아래와 같이 USArrests를 Hive 테이블로 변환해서 저장한다.

rhive.write.table(USArrests)	
  
	
  	
  
rhive.query("SELECT	
  *	
  FROM	
  USArrests	
  LIMIT	
  10")	
  
	
  	
  	
  	
  	
  	
  	
  rowname	
  murder	
  assault	
  urbanpop	
  rape	
  
1	
  	
  	
  	
  	
  	
  Alabama	
  	
  	
  13.2	
  	
  	
  	
  	
  236	
  	
  	
  	
  	
  	
  	
  58	
  21.2	
  
2	
  	
  	
  	
  	
  	
  	
  Alaska	
  	
  	
  10.0	
  	
  	
  	
  	
  263	
  	
  	
  	
  	
  	
  	
  48	
  44.5	
  
3	
  	
  	
  	
  	
  	
  Arizona	
  	
  	
  	
  8.1	
  	
  	
  	
  	
  294	
  	
  	
  	
  	
  	
  	
  80	
  31.0	
  
4	
  	
  	
  	
  	
  Arkansas	
  	
  	
  	
  8.8	
  	
  	
  	
  	
  190	
  	
  	
  	
  	
  	
  	
  50	
  19.5	
  
5	
  	
  	
  California	
  	
  	
  	
  9.0	
  	
  	
  	
  	
  276	
  	
  	
  	
  	
  	
  	
  91	
  40.6	
  
6	
  	
  	
  	
  	
  Colorado	
  	
  	
  	
  7.9	
  	
  	
  	
  	
  204	
  	
  	
  	
  	
  	
  	
  78	
  38.7	
  
7	
  	
  Connecticut	
  	
  	
  	
  3.3	
  	
  	
  	
  	
  110	
  	
  	
  	
  	
  	
  	
  77	
  11.1	
  
8	
  	
  	
  	
  	
  Delaware	
  	
  	
  	
  5.9	
  	
  	
  	
  	
  238	
  	
  	
  	
  	
  	
  	
  72	
  15.8	
  
9	
  	
  	
  	
  	
  	
  Florida	
  	
  	
  15.4	
  	
  	
  	
  	
  335	
  	
  	
  	
  	
  	
  	
  80	
  31.9	
  
10	
  	
  	
  	
  	
  Georgia	
  	
  	
  17.4	
  	
  	
  	
  	
  211	
  	
  	
  	
  	
  	
  	
  60	
  25.8

다음의 예는 USArrests 테이블의 전체 레코드 수를 카운트 하는 것이다.

rhive.query("SELECT	
  COUNT(*)	
  FROM	
  USArrests")	
  
	
  	
  X_c0	
  
1	
  	
  	
  50	
  

위의 예에서 사용한 COUNT 함수는 SQL에서 사용하는 함수이며 Hive UDF의 하나이다.
아마도 SQL문법에 익숙한 사용자라면 가장 많이 사용하는 SQL 내장 함수임을 알고
있을 것이다.
이제 이 COUNT 함수와 유사한 일을 하는 함수를 R로 작성해서 동작시키는 방법을
소개할 것이다.
우선 아래와 같이 USArrests 테이블의 description을 확인해 본다.

rhive.desc.table("USArrests")	
  
	
  	
  col_name	
  data_type	
  comment	
  
1	
  	
  rowname	
  	
  	
  	
  string	
  
2	
  	
  	
  murder	
  	
  	
  	
  double	
  
3	
  	
  assault	
  	
  	
  	
  	
  	
  	
  int	
  
4	
  urbanpop	
  	
  	
  	
  	
  	
  	
  int	
  
5	
  	
  	
  	
  	
  rape	
  	
  	
  	
  double

이제 USArrests 테이블에서 murder와 assault, rape 컬럼의 값을 모두 더하는 간단한
함수를 만들고 실행할 것이다.
다음은 그에 대한 전체 코드이다.

library(RHive)	
  
rhive.connect()	
  
	
  	
  
sumCrimes	
  <-­‐	
  function(column1,	
  column2,	
  column3)	
  {	
  
	
  	
  column1	
  +	
  column2	
  +	
  column3	
  
}	
  
	
  	
  
rhive.assign("sumCrimes",	
  sumCrimes)	
  
rhive.export("sumCrimes")	
  
	
  	
  
rhive.query("SELECT	
   rowname,	
   urbanpop,	
   R('sumCrimes',	
   murder,	
  
assault,	
  rape,	
  0.0)	
  FROM	
  usarrests")	
  
	
  	
  
rhive.close()

실행한 결과는 아래와 같다.

rhive.query("SELECT	
   rowname,	
   urbanpop,	
   R('sumCrimes',	
   murder,	
  
assault,	
  rape,	
  0.0)	
  AS	
  crimes	
  FROM	
  usarrests")	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  rowname	
  urbanpop	
  crimes	
  
1	
  	
  	
  	
  	
  	
  	
  	
  	
  Alabama	
  	
  	
  	
  	
  	
  	
  58	
  	
  270.4	
  
2	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Alaska	
  	
  	
  	
  	
  	
  	
  48	
  	
  317.5	
  
3	
  	
  	
  	
  	
  	
  	
  	
  	
  Arizona	
  	
  	
  	
  	
  	
  	
  80	
  	
  333.1	
  
...	
  
48	
  	
  West	
  Virginia	
  	
  	
  	
  	
  	
  	
  39	
  	
  	
  96.0	
  
49	
  	
  	
  	
  	
  	
  Wisconsin	
  	
  	
  	
  	
  	
  	
  66	
  	
  	
  66.4	
  
50	
  	
  	
  	
  	
  	
  	
  	
  Wyoming	
  	
  	
  	
  	
  	
  	
  60	
  	
  183.4

위의 예제에서 중요한 것은
SQL 구문내에 쓰여진 R() 이라는 펑션이다.
이 펑션은 Hive의 UDF function이며 R의 펑션이 아니다.
정확히는 RHive가 R의 펑션을 Hive에서 처리할 수 있도록 하기 위해서 RHive에서
Hive에 추가해 놓은 함수이다.
R() 펑션은 sum이나 avg, min과 같은 펑션이며 하는 일은
R로 작성된 펑션을 호출하고 인수를 넘겨주고 리턴값을 받아내서 Hive에 다시 전달해
주는 역할을 한다.
즉, 아래와 같은 SQL구문내에서 사용한 R() 펑션의 사용된 것을 설명하면

  SELECT	
   rowname,	
   urbanpop,	
   R('sumCrime',	
   murder,	
   assault,	
   rape,	
  
  0.0)	
  FROM	
  usarrests

'sumCrime'은 rhive.export에 의해 배포된 R 펑션의 이름이며,
뒤에 연달아오는 murder, assault, rape라는 것은 Hive 테이블의 컬럼 이름으로써
usarrests라는 Hive 테이블이 가지고 있는 column들의 이름이다.
그리고 R() 펑션에 입력된 마지막 인수인 0.0은 R() 펑션이 return 할 값의 type이다.
subCrime이라는 펑션이 리턴하는 값이 numeric인 경우에는 0.0을 입력하고
character인 경우에는 ""를 넣는다.
예를들어 subCrime이라는 R함수가 return하는 값이 character형이라면 아래와 같이
입력한다.

rhive.query("SELECT	
   rowname,	
   urbanpop,	
   R('sumCrime',	
   murder,	
  
assault,	
  rape,	
  "")	
  FROM	
  usarrests")

결국 아래의 구문은 앞서의 결과에서 보았듯이 3개의 컬럼으로 구성된 결과를 리턴한다.

SELECT	
   rowname,	
   urbanpop,	
   R('sumCrime',	
   murder,	
   assault,	
   rape,	
  
0.0)	
  FROM	
  usarrests
여기서 주의할 것은 R()펑션이 return하는 값은 하나 뿐이라는 것이다.
즉, 위의 예제의 SQL구문 결과를 보면 R() 펑션은 결과적으로 하나의 새로운
column값을 만드는 것을 알 수 있다.
사실 위의 예제에서 사용한 SQL구문은 원래 Hive SQL만으로도 처리가 가능한다.
실제로 아래의 2개의 구문은 동일한 결과를 보여준다.
RHive UDF SQL

rhive.query("SELECT	
   rowname,	
   urbanpop,	
   R('sumCrime',	
   murder,	
  
assault,	
  rape,	
  "")	
  FROM	
  usarrests")

Hive SQL

rhive.query("SELECT	
   rowname,	
   urbanpop,	
   murder	
   +	
   assault	
   +	
   rape	
  
AS	
  crimes	
  FROM	
  usarrests")

이 튜토리얼에서는 학습을 위해서 익히기 쉬운 예를 위해 실제로는 유용하지 않은 것을
예로 만든 것이다.
Hive는 기본적으로 많은 UDF와 column들간의 사칙연산등을 지원하고 있다.
여러분이 RHive을 이용해서 대용량 분석 작업을 할 때 만약 Hive SQL에 지원하는
기능이 이미 있고
그것으로 해결이 가능한 것이라면 UDF를 사용하기 전에 Hive SQL이 그것을
지원하는지 확인하고
그것을 이용해서 처리하는 것을 추천한다.
관련된 내용은 아래 URL에서 찾을 수 있다.
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
만약 Hive에서 기능을 지원하지 않고 여러 컬럼들을 이용해서 복잡한 계산을 하거나
데이터마이닝(data mining)이나 기계학습(machine learning)을 위한 자질(feature)
값을 추출하는 일을 해야 한다면
RHive UDF 기능이 매우 유용할 것이다.


RHive - UDAF 1
UDF와 유사한 것으로 Hive UDAF라는 것을 지원하고 있다.
UDAF는 aggregation을 위한 지원(support)하기 위한 것으로
SQL구문에서 "group by"에 의해 지정된 column의 값을 키(key)로 하여 취합된
데이터들에 대해서
순차적으로 어떤 연산을 수행하게 해주는 펑션이다.
이것 또한 UDF처럼 새로운 것을 Hive에 추가하기 위해서 Java로 모듈을 작성해야
하지만
RHive는 이것을 R언어를 이용해 작성할 수 있도록 지원하고 있다.
설명하지는 않았지만 앞서의 예제들에서 여러분은 sumAllcolumns라는 4개의 UDAF
펑션을 이미 보았다.
sumAllcolumns라는 이름으로 시작하는 펑션들은 입력된 인수의 값을 모두 더하는
일에 관련된 함수들이다.
여기서 여러분은 몇가지 의문을 가질 것이다.
첫째, "어째서 UDAF라는 기능은 4개의 펑션이 한꺼번에 필요한 것인가" 일것이고
둘째, UDAF는 어떤 것에 이용할 수 있는가" 일 것이다.
이를 이해하기 위해서는 먼저 실행코드를 보고 이해하는 것이 좋다.
먼저 UDAF용 함수들을 적용하기에 적절한 테이블을 만들기 위해서 R의 datasets에
기본 내장되어 있는
iris data를 Hive에 업로드 한다.

rhive.write.table(iris)	
  
	
  	
  
[1]	
  "iris"	
  
>	
  rhive.list.tables()	
  
	
  	
  	
  	
  	
  	
  	
  tab_name	
  
1	
  	
  	
  	
  	
  	
  	
  	
  	
  aids2	
  
2	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  iris	
  
3	
  new_usarrests	
  
4	
  	
  	
  	
  	
  usarrests	
  
	
  	
  
rhive.desc.table("iris")	
  
	
  	
  	
  	
  	
  col_name	
  data_type	
  comment	
  
1	
  	
  	
  	
  	
  rowname	
  	
  	
  	
  string	
  
2	
  sepallength	
  	
  	
  	
  double	
  
3	
  	
  sepalwidth	
  	
  	
  	
  double	
  
4	
  petallength	
  	
  	
  	
  double	
  
5	
  	
  petalwidth	
  	
  	
  	
  double	
  
6	
  	
  	
  	
  	
  species	
  	
  	
  	
  string	
  
	
  	
  
rhive.query("SELECT	
  *	
  FROM	
  iris	
  LIMIT	
  10")	
  
	
  	
  	
  rowname	
  sepallength	
  sepalwidth	
  petallength	
  petalwidth	
  species	
  
1	
  	
  	
  	
  	
  	
  	
  	
  1	
  	
  	
  	
  	
  	
  	
  	
  	
  5.1	
  	
  	
  	
  	
  	
  	
  	
  3.5	
  	
  	
  	
  	
  	
  	
  	
  	
  1.4	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
2	
  	
  	
  	
  	
  	
  	
  	
  2	
  	
  	
  	
  	
  	
  	
  	
  	
  4.9	
  	
  	
  	
  	
  	
  	
  	
  3.0	
  	
  	
  	
  	
  	
  	
  	
  	
  1.4	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
3	
  	
  	
  	
  	
  	
  	
  	
  3	
  	
  	
  	
  	
  	
  	
  	
  	
  4.7	
  	
  	
  	
  	
  	
  	
  	
  3.2	
  	
  	
  	
  	
  	
  	
  	
  	
  1.3	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
4	
  	
  	
  	
  	
  	
  	
  	
  4	
  	
  	
  	
  	
  	
  	
  	
  	
  4.6	
  	
  	
  	
  	
  	
  	
  	
  3.1	
  	
  	
  	
  	
  	
  	
  	
  	
  1.5	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
5	
  	
  	
  	
  	
  	
  	
  	
  5	
  	
  	
  	
  	
  	
  	
  	
  	
  5.0	
  	
  	
  	
  	
  	
  	
  	
  3.6	
  	
  	
  	
  	
  	
  	
  	
  	
  1.4	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
6	
  	
  	
  	
  	
  	
  	
  	
  6	
  	
  	
  	
  	
  	
  	
  	
  	
  5.4	
  	
  	
  	
  	
  	
  	
  	
  3.9	
  	
  	
  	
  	
  	
  	
  	
  	
  1.7	
  	
  	
  	
  	
  	
  	
  	
  0.4	
  	
  setosa	
  
7	
  	
  	
  	
  	
  	
  	
  	
  7	
  	
  	
  	
  	
  	
  	
  	
  	
  4.6	
  	
  	
  	
  	
  	
  	
  	
  3.4	
  	
  	
  	
  	
  	
  	
  	
  	
  1.4	
  	
  	
  	
  	
  	
  	
  	
  0.3	
  	
  setosa	
  
8	
  	
  	
  	
  	
  	
  	
  	
  8	
  	
  	
  	
  	
  	
  	
  	
  	
  5.0	
  	
  	
  	
  	
  	
  	
  	
  3.4	
  	
  	
  	
  	
  	
  	
  	
  	
  1.5	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
9	
  	
  	
  	
  	
  	
  	
  	
  9	
  	
  	
  	
  	
  	
  	
  	
  	
  4.4	
  	
  	
  	
  	
  	
  	
  	
  2.9	
  	
  	
  	
  	
  	
  	
  	
  	
  1.4	
  	
  	
  	
  	
  	
  	
  	
  0.2	
  	
  setosa	
  
10	
  	
  	
  	
  	
  	
  10	
  	
  	
  	
  	
  	
  	
  	
  	
  4.9	
  	
  	
  	
  	
  	
  	
  	
  3.1	
  	
  	
  	
  	
  	
  	
  	
  	
  1.5	
  	
  	
  	
  	
  	
  	
  	
  0.1	
  	
  setosa	
  

iris data가 어떻게 구성되어 있는지 대략 파악할 수 있을 것이다.
이제 iris 테이블에 species 컬럼의 값이 같은 것들이 취합해서 각 column의 값들을
더하는 작업을 할 것이며
그것의 완성된 전체코드와 실행결과는 아래와 같다.

sumAllColumns	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.partial	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
sumAllColumns.merge	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
 	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.terminate	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
rhive.assign("sumAllColumns",	
  sumAllColumns)	
  
rhive.assign("sumAllColumns.partial",	
  sumAllColumns.partial)	
  
rhive.assign("sumAllColumns.merge",	
  sumAllColumns.merge)	
  
rhive.assign("sumAllColumns.terminate",	
  sumAllColumns.terminate)	
  
	
  	
  
rhive.exportAll("sumAllColumns")	
  
	
  	
  
result	
  <-­‐	
  rhive.query("	
  
	
  	
  SELECT	
   species,	
   RA('sumAllColumns',	
   sepallength,	
   sepalwidth,	
  
petallength,	
  petalwidth)	
  
	
  	
  FROM	
  iris	
  
	
  	
  GROUP	
  BY	
  species")	
  
	
  	
  
print(result)	
  
	
  	
  	
  	
  	
  species	
  
1	
  	
  	
  	
  	
  setosa	
  
2	
  versicolor	
  
3	
  	
  virginica	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  X_c1	
  
1	
  
250.29999999999998,171.40000000000003,73.10000000000001,12.29999
9999999995	
  
2	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
   296.8,138.50000000000003,212.9999999
9999997,66.3	
  
3	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
   329.3999999999999,148.7,277.59999999999997,101.29
999999999998

위의 실행결과에서 마지막으로 출력(print)된 결과를 보면 컬럼이 2개인 3개의 레코드를
만들어 낸 것을 볼 수 있다.
먼저 주목할 것은 rhive.query로 전달된 SQL구문안에 있는 RA()라는 펑션이다.
이것은 R() 펑션과 비슷한 것으로 R로 작성된 펑션을 UDAF로 구동시켜주는 펑션이다.
RA()펑션의 return값은 모두 character type이며 하나의 값을 Hive로 전달한다.
그리고 Hive는 리턴받은 결과들을 처리하고 다시 최종적으로 RHive에 전달한다.
주의할 점의 RA() 펑션은 UDAF이므로 SQL의 GROUP BY 구문과 함께 사용해야만 한다.
이에 대한 자세한 내용은 Hive문서를 참조하라.
위에서 사용된 SQL구문을 구체적으로 설명하면

SELECT	
   species,	
   RA('sumAllColumns',	
   sepallength,	
   sepalwidth,	
  
petallength,	
  petalwidth)	
  
	
  	
  FROM	
  iris	
  
	
  	
  GROUP	
  BY	
  species

"GROUP BY"에 의해서 취합되는 species라는이름의 컬럼의 값들을 기준으로 모여진
데이터들끼리 연산을 따로 하는 것이다.
그리고 그 연산의 대상이 되는 컬럼들은 sepallength, sepalwidth, petallength,
petalwidth이며 RA() 펑션은 인수로 UDAF로 사용될 R펑션들의 접두어(prefix)를
입력받고 그 뒤로 두 번째 인수부터 사용자가 정의한 column들을 입력 받아서 R로
작성된 UDAF함수 4개를 각각 상황에 맞게 적용하여 처리한 것이다.
그리고 GROUP BY로 지정한 column인 species의 값과 UDAF에 의해 만들어진 값을
새로운 컬럼으로 생성하여 결과를 만들어 낸 것이다.
여기서 아직 앞서의 의문이 풀리지 않았을 것이며 또 추가로 여러분은 몇개의 의문이 더
생겼을지도 모른다.
아직 설명되지 않은 것들에 대해서는 다음 절에서 설명한다.


RHive - UDAF 2
이제 앞서의 예에서 만든 4개의 UDAF용 R펑션과 부족한 점을 설명할 것이다.
총 4개의 펑션이 UDAF를 위해서 만들어졌고 사용되었는데 아래와 같다.

sumAllColumns	
  
sumAllColumns.partial	
  
sumAllColumns.merge	
  
sumAllColumns.terminate	
  

RHive 용 UDAF 펑션들은 같은 유저가 임의로 지정하는 prefix로 시작하는 4개의
펑션들로 구성되어야 하며 postfix로는 .partial, .merge, .terminate 그리고 postfix가
없는 이름을 가진 함수들로 작성되어야 한다.
이것은 RHive에 정한 naming rule로 바꿀 수 없다.
4개의 펑션이 필요한 이유는 Hive UDAF가 작동될 때 function들이 작동할 수 있는
Map/Reduce 과정에서의 포인트가 4곳이기 때문이다.
foobar라는 이름으로 시작하는 UDAF 함수 4개를 만들었다고 가정하면 각 펑션별로
작동되는 곳들은 아래와 같다.

 foobar	
  -­‐	
  Map의	
  aggregation을	
  수행하는	
  곳	
  (정확히는	
  combine	
  단계)	
  
 foobar.partial	
  -­‐	
  Map의	
  aggregation	
  된	
  결과를	
  reduce에	
  전달하는	
  곳	
  
 foobar.merge	
  -­‐	
  Reduce의	
  aggregation을	
  수행하는	
  곳	
  
 foobar.terminate	
   -­‐	
   Reduce에서	
   최종	
   aggregation	
   된	
   것을	
   종료하는	
  
 곳

그리고 foobar와 foobar.merge는 유사한 일을 하며 이름은 상관없지만 인수는 2개를
가지고 있어야 하며
foobar.partial과 foobar.terminate도 역시 서로 비슷하며 이것들은 이름은 상관없지만
인수를 1개만 가질 수 있다.
이제 이 함수들이 어떻게 언제 작동되는지에 대한 것이 아직도 의문으로 남아 있을
것이다.
이제 이 4개의 함수들이 어떻게 서로 연결되어 작동하는지 이해하기 위해
함수들이 작동되는 흐름을 알아여 하는데 그것은 아래와 같다.

foobar	
  -­‐	
  combine	
  aggregation	
  (map)	
  
foobar.partial	
  -­‐	
  combine	
  return	
  (map)	
  
foobar.merge	
  -­‐	
  reduce	
  aggregation	
  
foobar.terminate	
  -­‐	
  reduce	
  terminate	
  

여기서 combine 단계는 Hive의 설정에 따라 처리되지 않고 통과(pass)하고
모든 것을 reduce 단계에서 처리될 수도 있다.
설정을 정확하게 하지 않는다면 이 함수부분이 언제 통과하고 언제 수행되는지를 알기
어렵다.
따라서 4개의 펑션을 모두 만들어 놓는 것이 안전하다.
고급 지식과 완벽한 이해를 위해서는 Hive와 Hadoop의 문서를 참조하라.
완벽한 이해가 아닌 사용법만을 이해하고 싶다면
RHive를 UDAF 지원을 이용하기 위해서는 펑션을 4개 만들어야 하며 정해진 룰에
따라야 한다는 것을 기억해야 한다.


RHive - UDAF 3
이제 UDAF용 4개의 펑션들의 인수들과 작동 방식에 대해서 설명할 것이다.
앞서 예제에서 만든 sumAllColumns라는 펑션들 중
sumAllColumns와 sumAllColumns.merge를 살펴보자.
두 함수내의 코드는 동일하다.

sumAllColumns	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.merge	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}

이 함수들은 인수를 2개를 처리해야만 하는데
첫번째 인수는 sumAllColumns와 sumAllColumns.merge함수에서 return한 값이
다시 sumAllColumns와 sumAllColumns.merge함수의 인수로 들어오는 것이다.
두번째 인수는 현재 record에 대해서 Hive가 넘겨주는 값이다.
첫번째와 두번째 인수는 실제로 모두 vector이거나 list이다.
vector로 넘겨지기 때문 각각의 column들에 대해서는 SQL 구문에서 입력한
column들의 순서를 기억할 필요가 있다.
첫번째 인수로 넘겨지는 prev는 함수가 return한 값이 다시 돌아서 넘겨지는 것이므로
함수가 맨처음 실행될 때는 값이 없는 NULL 상태로 넘겨지게 된다.
그래서 함수내에서 is.null로 NULL인지 확인하고 처리한 것을 볼 수 있다.
if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }

이렇게 반복적으로 수행되어서 마지막에 레코드에서 return되는 값들은
sumAllColumns.partial과 sumAllColumns.terminate의 인수로 각각 넘겨진다.
두 함수의 함수내 코드는 동일하다.

sumAllColumns.partial	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
sumAllColumns.terminate	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}

이 두 함수들은 반복적으로 수행되지 않으며 그 때문에 인수를 하나만 받을 수 있다.
그리고 4개의 함수중에 가장 마지막에 실행되는 sumAllColumns.terminate가
return한 값은
Hive로 전달되며 하나의 column의 값으로 만들어진다.
위 예제에서는 각각 2개씩의 함수들이 동일한 코드를 가지고 있는 것을 볼 수 있는데
이 튜토리얼에서는 이것 역시 설명을 위한 쉬운 예제를 만든 것으로
실제 사용할 때는 사용자에 의해서 4개의 펑션이 모두 다른 코드를 가질 수도 있다.
그래서 함수내의 코드가 동일하다고 해도 항상 4개의 함수가 있어야 한다.


RHive - UDTF
이제 앞의 예에서 작성한 코드의 결과값을 좀더 우아하게(graceful)하게 고치려고 한다.
character(string)값 하나로 나오는 것은 다루기가 매우 힘들기 때문이다.
이것을 분해할 필요가 있으며 이를 위해서 RHive가 지원하는 UDTF 펑션인 unfold를
사용할 것이다.
그 결과가 앞서 예에서 SQL 구문을 실행한 결과이다.

  print(result)	
  
  	
  	
  	
  	
  	
  species	
  
  1	
  	
  	
  	
  	
  setosa	
  
2	
  versicolor	
  
  3	
  	
  virginica	
  
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
  	
  	
  	
  	
  	
  	
  	
  	
  	
  X_c1	
  
  1	
  
  250.29999999999998,171.40000000000003,73.10000000000001,12.2999
  99999999995	
  
  2	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
   296.8,138.50000000000003,212.999999
  99999997,66.3	
  
  3	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
   329.3999999999999,148.7,277.59999999999997,101.2
  9999999999998	
  

위에서 2번째 컬럼인 X_c1은 UDAF에 의해서 만들어진 값이며 character type으로
되어 있다.
그리고 값으로는 수치값들이 "," 로 구분되어 있음을 알 수 있다.
이것을 다시 numeric vector로 만들기 위해서는 strsplit과 같은 R 내장함수를 이용해야
하는데
record수가 적을 때는 문제가 없지만 record 수가 많다면 처리하는데 문제가 발생한다.
위의 예에서는 레코드수가 고작 3개이지만 크기가 큰 테이블에 비슷한 처리를 할 때는
record수가 3,000,000개가 넘을 수도 있다.
따라서 UDAF가 return한 값은 구분되어 각각의 column값으로 만들어져야 한다.
이것을 위해서는 subquery와 UDTF가 필요하며
UDTF를 사용해서 수정된 코드는 아래와 같다.

sumAllColumns	
  <-­‐	
  function(prev,	
  values)	
  {	
  
	
  	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.partial	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
sumAllColumns.merge	
  <-­‐	
  function(prev,	
  values)	
  {	
  
 	
  if	
  (is.null(prev))	
  {	
  
	
  	
  	
  	
  prev	
  <-­‐	
  rep(0.0,	
  length(values))	
  
	
  	
  }	
  
	
  	
  prev	
  +	
  values	
  
}	
  
	
  	
  
sumAllColumns.terminate	
  <-­‐	
  function(values)	
  {	
  
	
  	
  values	
  
}	
  
	
  	
  
rhive.assign("sumAllColumns",	
  sumAllColumns)	
  
rhive.assign("sumAllColumns.partial",	
  sumAllColumns.partial)	
  
rhive.assign("sumAllColumns.merge",	
  sumAllColumns.merge)	
  
rhive.assign("sumAllColumns.terminate",	
  sumAllColumns.terminate)	
  
	
  	
  
rhive.exportAll("sumAllColumns")	
  
	
  	
  
result	
  <-­‐	
  rhive.query(	
  
	
  	
  "SELECT	
   unfold(dummytable.dummycolumn,	
   0.0,	
   0.0,	
   0.0,	
   0.0,	
  
',')	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  AS	
     (sepallength,	
                              sepalwidth,	
                       petallength,	
  
petalwidth)	
  
	
  	
  	
  FROM	
  (	
  
	
  	
  	
  	
  	
  SELECT	
   RA('sumAllColumns',	
   sepallength,	
                                                                      sepalwidth,	
  
petallength,	
  petalwidth)	
  AS	
  dummycolumn	
  
	
  	
  	
  	
  	
  FROM	
  iris	
  
	
  	
  	
  	
  	
  GROUP	
  BY	
  species	
  
	
  	
  	
  	
  	
  )	
  dummytable")	
  
	
  	
  
print(result)	
  
	
  	
  sepallength	
  sepalwidth	
  petallength	
  petalwidth	
  
1	
  	
  	
  	
  	
  	
  	
  250.3	
  	
  	
  	
  	
  	
  171.4	
  	
  	
  	
  	
  	
  	
  	
  73.1	
  	
  	
  	
  	
  	
  	
  12.3	
  
2	
  	
  	
  	
  	
  	
  	
  296.8	
  	
  	
  	
  	
  	
  138.5	
  	
  	
  	
  	
  	
  	
  213.0	
  	
  	
  	
  	
  	
  	
  66.3	
  
3	
  	
  	
  	
  	
  	
  	
  329.4	
  	
  	
  	
  	
  	
  148.7	
  	
  	
  	
  	
  	
  	
  277.6	
  	
  	
  	
  	
  	
  101.3	
  

SQL문이 다소 복잡해 졌으나 최종결과에서 UDAF가 return값이
모두 unfold라는 UDTF에 의해서 각각의 column들로 분리되어 만들어진 것을 볼 수
있다.
unfold는 RHive에 지원하는 UDTF 함수이며 R코드를 따로 적용할 필요는 없다.
그리고 Hive의 UDTF는 현재 제약으로 인해 SELECT절에 다른 구문을 넣을 수 없다는
단점이 있다.
이것은 RHive에서는 해결할 수 없는 것으로 Hive의 기능이 개선될 때까지 기다려야 할
것이다.
지금까지의 UDF, UDAF, UDTF는 SQL구문을 이용해서 1단계 Map/Reduce로 작업이
처리되도록 한 것이다.
만약 여러분이 RHive를 이용해서 매우 복잡한 작업을 하려고 한다면
여러 단계의 Map/Reduce가 필요 할 수 있다.
이것은 일반적인 Map/Reduce 구현체(implementation)이나 Hadoop streaming
구현체에서 흔히 볼 수 있는 것이다.
이런 여러 단계의 Map/Reduce를 결합해서 작업을 하려고 한다면
중간 결과를 저장하기 위한 임시 테이블을 만들어 두고 결과를 저장한 후 삭제하는
작업을 해야 할 수 있다.

More Related Content

What's hot

#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁
#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁
#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁탑크리에듀(구로디지털단지역3번출구 2분거리)
 
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Function calling convention
Function calling conventionFunction calling convention
Function calling conventionYuk SeungChan
 
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지탑크리에듀(구로디지털단지역3번출구 2분거리)
 
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Ji Hun Kim
 
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육탑크리에듀(구로디지털단지역3번출구 2분거리)
 
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지탑크리에듀(구로디지털단지역3번출구 2분거리)
 
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천탑크리에듀(구로디지털단지역3번출구 2분거리)
 
파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄 파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄 SeongHyun Ahn
 
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은jieun kim
 
파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄SeongHyun Ahn
 
파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄SeongHyun Ahn
 

What's hot (16)

#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁
#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁
#6.SQL초보에서 Schema Objects까지_구로IT학원/오라클교육/자바교육/국비지원/재직자환급교육/내일배움카드/사업주위탁
 
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지
[오라클교육/SQL교육/IT교육/실무중심교육학원추천_탑크리에듀]#4.SQL초보에서 Schema Objectes까지
 
Function calling convention
Function calling conventionFunction calling convention
Function calling convention
 
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지
(재직자환급교육/사업주위탁/IT실무교육/구로IT학원/오라클교육/SQL기초강좌/IT강좌)#10.SQL초보에서 Schema Objects까지
 
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)
#12.SQL초보에서 schema Objects까지(구로IT학원/IT실무교육학원/국비지원IT교육학원/오라클교육/자바교육/닷넷교육학원추천)
 
Learning Node Book, Chapter 5
Learning Node Book, Chapter 5Learning Node Book, Chapter 5
Learning Node Book, Chapter 5
 
Stack frame
Stack frameStack frame
Stack frame
 
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육
(SQL초보자를 위한, 쿼리최적화 for SQL튜닝)SQL쿼리작성Tip,최적화팁,최적화된SQL작성방법교육
 
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지
오라클강의/자바강의/닷넷강의/자마린교육/아두이노교육학원추천_#13.SQL초보에서 Schema Objects까지
 
IT실무교육학원/자바학원/오라클학원/SQL기초학원추천_#11.SQL초보에서 Schema Objects까지
IT실무교육학원/자바학원/오라클학원/SQL기초학원추천_#11.SQL초보에서 Schema Objects까지IT실무교육학원/자바학원/오라클학원/SQL기초학원추천_#11.SQL초보에서 Schema Objects까지
IT실무교육학원/자바학원/오라클학원/SQL기초학원추천_#11.SQL초보에서 Schema Objects까지
 
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
#2.SQL초보에서 Schema Objects까지_재직자/근로자환급/국비지원교육/IT실무교육/SQL기초교육/구로IT학원추천
 
파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄 파이썬 웹프로그래밍 1탄
파이썬 웹프로그래밍 1탄
 
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
(오라클힌트/SQL튜닝 강좌)쿼리튜닝을 위한 오라클의 10053 이벤트
 
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
 
파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄파이썬 데이터베이스 연결 1탄
파이썬 데이터베이스 연결 1탄
 
파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄
 

Similar to RHive tutorial 4: RHive 튜토리얼 4 - UDF, UDTF, UDAF 함수

R 기초 : R Basics
R 기초 : R BasicsR 기초 : R Basics
R 기초 : R BasicsYoonwhan Lee
 
Macro & compilation
Macro & compilationMacro & compilation
Macro & compilationIkhoon Eom
 
R 프로그램의 이해와 활용 v1.1
R 프로그램의 이해와 활용 v1.1R 프로그램의 이해와 활용 v1.1
R 프로그램의 이해와 활용 v1.1happychallenge
 
Lua 문법 -함수
Lua 문법 -함수Lua 문법 -함수
Lua 문법 -함수Jaehoon Lee
 
Data Mining with R CH1 요약
Data Mining with R CH1 요약Data Mining with R CH1 요약
Data Mining with R CH1 요약Sung Yub Kim
 
R 프로그래밍 기본 문법
R 프로그래밍 기본 문법R 프로그래밍 기본 문법
R 프로그래밍 기본 문법Terry Cho
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법SeongHyun Ahn
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선daewon jeong
 
Perl Script Document
Perl Script DocumentPerl Script Document
Perl Script Document오석 한
 
0327.web&ruby&rails
0327.web&ruby&rails0327.web&ruby&rails
0327.web&ruby&rails민정 김
 
R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작Terry Cho
 

Similar to RHive tutorial 4: RHive 튜토리얼 4 - UDF, UDTF, UDAF 함수 (20)

R 기초 : R Basics
R 기초 : R BasicsR 기초 : R Basics
R 기초 : R Basics
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
Macro & compilation
Macro & compilationMacro & compilation
Macro & compilation
 
R 프로그램의 이해와 활용 v1.1
R 프로그램의 이해와 활용 v1.1R 프로그램의 이해와 활용 v1.1
R 프로그램의 이해와 활용 v1.1
 
Lua 문법 -함수
Lua 문법 -함수Lua 문법 -함수
Lua 문법 -함수
 
Haskell study 5
Haskell study 5Haskell study 5
Haskell study 5
 
R 시작해보기
R 시작해보기R 시작해보기
R 시작해보기
 
Data Mining with R CH1 요약
Data Mining with R CH1 요약Data Mining with R CH1 요약
Data Mining with R CH1 요약
 
자바 8 학습
자바 8 학습자바 8 학습
자바 8 학습
 
R 프로그래밍 기본 문법
R 프로그래밍 기본 문법R 프로그래밍 기본 문법
R 프로그래밍 기본 문법
 
Apply교육
Apply교육Apply교육
Apply교육
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법
 
Haskell study 9
Haskell study 9Haskell study 9
Haskell study 9
 
Haskell study 4
Haskell study 4Haskell study 4
Haskell study 4
 
나에 첫번째 자바8 람다식 지앤선
나에 첫번째 자바8 람다식   지앤선나에 첫번째 자바8 람다식   지앤선
나에 첫번째 자바8 람다식 지앤선
 
Perl Script Document
Perl Script DocumentPerl Script Document
Perl Script Document
 
0327.web&ruby&rails
0327.web&ruby&rails0327.web&ruby&rails
0327.web&ruby&rails
 
R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작
 
Java8 람다
Java8 람다Java8 람다
Java8 람다
 
Hive begins
Hive beginsHive begins
Hive begins
 

More from Aiden Seonghak Hong

RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수
RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수
RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수Aiden Seonghak Hong
 
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정Aiden Seonghak Hong
 
R hive tutorial supplement 3 - Rstudio-server setup for rhive
R hive tutorial supplement 3 - Rstudio-server setup for rhiveR hive tutorial supplement 3 - Rstudio-server setup for rhive
R hive tutorial supplement 3 - Rstudio-server setup for rhiveAiden Seonghak Hong
 
R hive tutorial supplement 2 - Installing Hive
R hive tutorial supplement 2 - Installing HiveR hive tutorial supplement 2 - Installing Hive
R hive tutorial supplement 2 - Installing HiveAiden Seonghak Hong
 
R hive tutorial supplement 1 - Installing Hadoop
R hive tutorial supplement 1 - Installing HadoopR hive tutorial supplement 1 - Installing Hadoop
R hive tutorial supplement 1 - Installing HadoopAiden Seonghak Hong
 
R hive tutorial - apply functions and map reduce
R hive tutorial - apply functions and map reduceR hive tutorial - apply functions and map reduce
R hive tutorial - apply functions and map reduceAiden Seonghak Hong
 
R hive tutorial - udf, udaf, udtf functions
R hive tutorial - udf, udaf, udtf functionsR hive tutorial - udf, udaf, udtf functions
R hive tutorial - udf, udaf, udtf functionsAiden Seonghak Hong
 
RHive tutorials - Basic functions
RHive tutorials - Basic functionsRHive tutorials - Basic functions
RHive tutorials - Basic functionsAiden Seonghak Hong
 

More from Aiden Seonghak Hong (11)

IoT and Big data with R
IoT and Big data with RIoT and Big data with R
IoT and Big data with R
 
RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수
RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수
RHive tutorial 3: RHive 튜토리얼 3 - HDFS 함수
 
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정
RHive tutorial 1: RHive 튜토리얼 1 - 설치 및 설정
 
R hive tutorial supplement 3 - Rstudio-server setup for rhive
R hive tutorial supplement 3 - Rstudio-server setup for rhiveR hive tutorial supplement 3 - Rstudio-server setup for rhive
R hive tutorial supplement 3 - Rstudio-server setup for rhive
 
R hive tutorial supplement 2 - Installing Hive
R hive tutorial supplement 2 - Installing HiveR hive tutorial supplement 2 - Installing Hive
R hive tutorial supplement 2 - Installing Hive
 
R hive tutorial supplement 1 - Installing Hadoop
R hive tutorial supplement 1 - Installing HadoopR hive tutorial supplement 1 - Installing Hadoop
R hive tutorial supplement 1 - Installing Hadoop
 
R hive tutorial - apply functions and map reduce
R hive tutorial - apply functions and map reduceR hive tutorial - apply functions and map reduce
R hive tutorial - apply functions and map reduce
 
R hive tutorial - udf, udaf, udtf functions
R hive tutorial - udf, udaf, udtf functionsR hive tutorial - udf, udaf, udtf functions
R hive tutorial - udf, udaf, udtf functions
 
RHive tutorial - HDFS functions
RHive tutorial - HDFS functionsRHive tutorial - HDFS functions
RHive tutorial - HDFS functions
 
RHive tutorials - Basic functions
RHive tutorials - Basic functionsRHive tutorials - Basic functions
RHive tutorials - Basic functions
 
RHive tutorial - Installation
RHive tutorial - InstallationRHive tutorial - Installation
RHive tutorial - Installation
 

RHive tutorial 4: RHive 튜토리얼 4 - UDF, UDTF, UDAF 함수

  • 1. RHive 튜토리얼 4 - UDF, UDAF, UDTF 함수 RHive - advanced functions RHive는 기초함수(basic functions), HDFS, map/reduce를 위한 apply 계열, 그리고 UDF, UDAF, UDTF를 지원하기 위한 고급 함수들을 지원한다. Advanced function들은 Hive의 UDF와 UDAF를 R로 구현하여 적용하는데 필요한 UDF/UDAF 함수들로 구성되어 있다. 이 함수들을 활용하면 매우 낮은 복잡한 수준까지 R을 적용하여 Hadoop과 Hive를 이용한 Map/Reduce 프로그래밍을 할 수 있으며 Data mining의 복잡한 알고리즘이나 데이터 프로세싱도 많은 부분을 R언어를 이용해서 처리할 수 있다. RHive - UDF and UDAF functions Hive는 UDF(User Defined Function), UDAF(User Defined Aggregate Function), UDTF(User Defined Table create Function)을 제공한다. UDF는 count, avg, min, max와 같은 SQL구문으로 한 컬럼 또는 여러 컬럼에 대해 연산을 수행하는 Hive의 내장된 function을 말한다. Hive는 기본적으로 몇개의 UDF를 지원하며 사용자가 개발하여 추가할 수 있다. 하지만 원래 Hive에서의 UDF, UDAF, UDTF는 모두 Java로 작성되어야 하며 R언어를 직접 사용할 수 없다. RHive는 UDF와 UDAF를 R언어로 작성하고 Hive에서 수행할 수 있게 기능을 지원한다. 또 RHive가 미리 작성해 둔 UDTF를 활용하여 복잡한 컬럼 분해 작업을 가능하게 해준다. 이 튜토리얼에서는 UDF와 UDAF작성할 때 사용하는 함수들과 예제를 통해 이것들을 어떻게 구현하고 적용하는지를 설명한다. rhive.assign rhive.assign 함수는 R에서 작성된 함수들과 생성한 변수들을 Hive에서 참조할 수 있게 지정하는 역할을 한다.
  • 2. 이같은 assign이 과정이 필요한 이유는 R에서 작성한 코드와 벡터, 매트릭스, 데이터프레임, 펑션들 중 어느 것이 분산환경에서 사용될 것인지 지정(assign)해 주는 작업이 필요하기 때문이다. rhive.assign이 바로 분산환경으로 내보내기 위한 함수와 변수, 객체들을 지정하는 일을 한다. 주의할 점은 rhive.assign는 분산환경으로 함수와 변수, 객체들을 배포하기 전에 필요한 작업들을 수행하지만 실제로 분산환경에서 배포하지는 않는다. 단지 준비를 위한 것으로 실제로 배포작업을 해주는 rhive.export나 rhive.exporlAll과 같은 펑션들과 연달아 쓰이는 것이 일반적이다. 배포의 의미는 Hadoop의 Map/Reduce처럼 Hive에서 사용될 함수와 객체들을 Hadoop의 Job node에 미리 대기시켜 두었다가 데이터를 처리할 때 불러 쓰기 위한 준비과정으로 생각하면 된다. rhive.assign 함수는 인수(argument)를 2개 입력받으며 첫번째는 R에서 생성한 심볼의 character type의 alias이며 두 번째는 배포할 심볼 자체이다. 만약 분산환경에 전달할 심볼이 newsum이라는 이름을 가지고 있다면 rhive.assign을 사용하여 다음과 같이 지정해준다. newsum  <-­‐  function(value)  {      value  +  1   }   rhive.assign("newsum",  newsum) 구문이 다소 어색해 보일 수는 있지만 이것은 R의 구조로 인한 문제로 향후 버전에서 개선될 것이다. 첫번째 인수에는 두번째 인수로 들어갈 심볼을 문자열로 만들어주기만 하면 된다. 보통은 심볼의 이름과 같은 문자열을 넣어주는 것이 작업하는데 편리하며 심볼가 동일 하지 않은 다른 문자열을 주어도 상관없지만 이름을 바꾸는 경우 실제 사용할때는 지정한 심볼의 이름이 바뀌는 것을 주의해야 하고 혼동하기 쉬우므로 바꾸지 않는 것이 좋다. 다음에 나오는 예를 통해 rhive.assign을 사용하는 방법을 살펴보자. 다음 사용예는 sum3values라는 function 만들고 rhive.assign을 이용해서 분산환경에 배포될 것들을 정의한 예이다. sum3values  <-­‐  function(a,b,c)  {      a  +  b  +  c   }  
  • 3.     rhive.assign("sum3values",  sum3values)   [1]  TRUE 아래와 같이 함수가 아닌 객체를 지정할 수도 있다. coef1  <-­‐  3.141593   rhive.assign("coef1",  coef1) 데이터프레임을 비롯한 어떤 것도 가능하다. library(MASS)   >  head(cats)      Sex  Bwt  Hwt   1      F  2.0  7.0   2      F  2.0  7.4   3      F  2.0  9.5   4      F  2.1  7.2   5      F  2.1  7.3   6      F  2.1  7.6   >  rhive.assign("cats",  cats)   [1]  TRUE 객체와 dataframe등은 분산환경에 배포해서 기존에 만들어둔 값이나 coefficient등을 참조해서 연산하는데 이용할 수 있다. 다만 이런 객체들이 분산환경으로 배포되면 분산환경내에서는 공유메모리(shared memory)와 같은 개념이 아니고 단지 local memory에 존재하는 것들이므로 주의해야 한다. rhive.export rhive.export는 R에서 만들어진 객체들을 분산환경에 실제로 배포해서 분산환경에서 실행되도록 준비하는 것을 처리해 준다. rhive.export는 rhive.assign과 함께 사용되며 rhive.export의 인수로 주는 객체의 이름들은 반드시 rhive.assign으로 배포준비가 끝난 것이어야 한다. 다음의 예를 통해서 사용법을 쉽게 알 수 있다.
  • 4. sum3values  <-­‐  function(a,b,c)  {      a  +  b  +  c   }       rhive.assign("sum3values",  sum3values)       rhive.export(sum3values) rhive.export는 첫번째 인수(argument)인 exportname을 제외하고도 많은 인수를 가지고 있다. 하지만 이런 것들은 복잡하게 구성된 환경에서 사용될 수 있도록 배포할 서버와 port등을 별도로 지정할 수 있게 해 둔 것으로 보통의 경우에는 사용할 필요가 없다. 이런것들을 사용해야 할 만큼 RHive를 복잡한 환경에 구성해야 한다면 매뉴얼을 참조하거나 RHive 개발팀에 문의하도록 한다. rhive.exportAll rhive.exportAll 함수느 rhive.export와 기능상으로 동일한 함수이지만 다른점은 rhive.exportAll은 인수로 넘겨준 문자열로 시작하는 심볼을 모두 한꺼번에 넘겨주는 역할을 한다. 이 함수는 주로 R로 작성된 UDAF function을 배포하기 위한 용도로 사용된다. R로 작성된 UDAF 펑션은 같은 이름으로 시작하는 4개 펑션으로 구성되어야 하는 제약이 있으며 이것들을 쉽게 배포하기 위해 만들어둔 일종의 rhive.export를 변형한 함수이다. 다음의 예는 4개의 함수를 만들고 이것들을 분산환경의 RHive 서버로 배포하는 작업을 한다. sumAllColumns  <-­‐  function(prev,  values)  {          if  (is.null(prev))  {                  prev  <-­‐  rep(0.0,  length(values))          }              prev  +  values   }      
  • 5. sumAllColumns.partial  <-­‐  function(values)  {      values   }       sumAllColumns.merge  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {          prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   }       sumAllColumns.terminate  <-­‐  function(values)  {          values   }       rhive.assign("sumAllColumns",  sumAllColumns)   rhive.assign("sumAllColumns.partial",  sumAllColumns.partial)   rhive.assign("sumAllColumns.merge",  sumAllColumns.merge)   rhive.assign("sumAllColumns.terminate",  sumAllColumns.terminate)       rhive.exportAll("sumAllColumns")   실제로 위에서 마지막줄은 다음과 동일하다. #  rhive.exportAll("sumAllColumns")       rhive.export("sumAllColumns")   rhive.export("sumAllColumns.partial")   rhive.export("sumAllColumns.merge")   rhive.export("sumAllColumns.terminate") rhive.assign과 rhive.export, rhive.exportAll은 R에서 생성한 펑션과 객체들을 분산환경에서 가동중인 Rserve로 전달하여 Hive와 Hadoop이 사용할 수 있도록 준비하는 작업까지만 수행한다.
  • 6. 이렇게 배포한 R 펑션과 객체들을 실제로 사용하기 위해서는 rhive.query에 전달하는 SQL구문에 기술해야만 사용할 수 있다. 다음에 나오는 예제들을 통해 배포한 함수들을 어떻게 작동시키는지 배우게 될 것이다. RHive - UDF usage 이제 UDF를 적용해 볼 테이블을 하나 준비해야 한다. Hive에 UDF를 테스트해 볼 적당한 테이블이 없다면 테이블을 하나 만든다. 이 튜토리얼에서는 USArrests라는 data를 Hive 테이블로 변환할 것이다. USArrests는 R이 원래 가지고 있는 작은 데이터이다. 아래와 같이 USArrests를 Hive 테이블로 변환해서 저장한다. rhive.write.table(USArrests)       rhive.query("SELECT  *  FROM  USArrests  LIMIT  10")                rowname  murder  assault  urbanpop  rape   1            Alabama      13.2          236              58  21.2   2              Alaska      10.0          263              48  44.5   3            Arizona        8.1          294              80  31.0   4          Arkansas        8.8          190              50  19.5   5      California        9.0          276              91  40.6   6          Colorado        7.9          204              78  38.7   7    Connecticut        3.3          110              77  11.1   8          Delaware        5.9          238              72  15.8   9            Florida      15.4          335              80  31.9   10          Georgia      17.4          211              60  25.8 다음의 예는 USArrests 테이블의 전체 레코드 수를 카운트 하는 것이다. rhive.query("SELECT  COUNT(*)  FROM  USArrests")      X_c0   1      50   위의 예에서 사용한 COUNT 함수는 SQL에서 사용하는 함수이며 Hive UDF의 하나이다. 아마도 SQL문법에 익숙한 사용자라면 가장 많이 사용하는 SQL 내장 함수임을 알고 있을 것이다.
  • 7. 이제 이 COUNT 함수와 유사한 일을 하는 함수를 R로 작성해서 동작시키는 방법을 소개할 것이다. 우선 아래와 같이 USArrests 테이블의 description을 확인해 본다. rhive.desc.table("USArrests")      col_name  data_type  comment   1    rowname        string   2      murder        double   3    assault              int   4  urbanpop              int   5          rape        double 이제 USArrests 테이블에서 murder와 assault, rape 컬럼의 값을 모두 더하는 간단한 함수를 만들고 실행할 것이다. 다음은 그에 대한 전체 코드이다. library(RHive)   rhive.connect()       sumCrimes  <-­‐  function(column1,  column2,  column3)  {      column1  +  column2  +  column3   }       rhive.assign("sumCrimes",  sumCrimes)   rhive.export("sumCrimes")       rhive.query("SELECT   rowname,   urbanpop,   R('sumCrimes',   murder,   assault,  rape,  0.0)  FROM  usarrests")       rhive.close() 실행한 결과는 아래와 같다. rhive.query("SELECT   rowname,   urbanpop,   R('sumCrimes',   murder,   assault,  rape,  0.0)  AS  crimes  FROM  usarrests")  
  • 8.                    rowname  urbanpop  crimes   1                  Alabama              58    270.4   2                    Alaska              48    317.5   3                  Arizona              80    333.1   ...   48    West  Virginia              39      96.0   49            Wisconsin              66      66.4   50                Wyoming              60    183.4 위의 예제에서 중요한 것은 SQL 구문내에 쓰여진 R() 이라는 펑션이다. 이 펑션은 Hive의 UDF function이며 R의 펑션이 아니다. 정확히는 RHive가 R의 펑션을 Hive에서 처리할 수 있도록 하기 위해서 RHive에서 Hive에 추가해 놓은 함수이다. R() 펑션은 sum이나 avg, min과 같은 펑션이며 하는 일은 R로 작성된 펑션을 호출하고 인수를 넘겨주고 리턴값을 받아내서 Hive에 다시 전달해 주는 역할을 한다. 즉, 아래와 같은 SQL구문내에서 사용한 R() 펑션의 사용된 것을 설명하면 SELECT   rowname,   urbanpop,   R('sumCrime',   murder,   assault,   rape,   0.0)  FROM  usarrests 'sumCrime'은 rhive.export에 의해 배포된 R 펑션의 이름이며, 뒤에 연달아오는 murder, assault, rape라는 것은 Hive 테이블의 컬럼 이름으로써 usarrests라는 Hive 테이블이 가지고 있는 column들의 이름이다. 그리고 R() 펑션에 입력된 마지막 인수인 0.0은 R() 펑션이 return 할 값의 type이다. subCrime이라는 펑션이 리턴하는 값이 numeric인 경우에는 0.0을 입력하고 character인 경우에는 ""를 넣는다. 예를들어 subCrime이라는 R함수가 return하는 값이 character형이라면 아래와 같이 입력한다. rhive.query("SELECT   rowname,   urbanpop,   R('sumCrime',   murder,   assault,  rape,  "")  FROM  usarrests") 결국 아래의 구문은 앞서의 결과에서 보았듯이 3개의 컬럼으로 구성된 결과를 리턴한다. SELECT   rowname,   urbanpop,   R('sumCrime',   murder,   assault,   rape,   0.0)  FROM  usarrests
  • 9. 여기서 주의할 것은 R()펑션이 return하는 값은 하나 뿐이라는 것이다. 즉, 위의 예제의 SQL구문 결과를 보면 R() 펑션은 결과적으로 하나의 새로운 column값을 만드는 것을 알 수 있다. 사실 위의 예제에서 사용한 SQL구문은 원래 Hive SQL만으로도 처리가 가능한다. 실제로 아래의 2개의 구문은 동일한 결과를 보여준다. RHive UDF SQL rhive.query("SELECT   rowname,   urbanpop,   R('sumCrime',   murder,   assault,  rape,  "")  FROM  usarrests") Hive SQL rhive.query("SELECT   rowname,   urbanpop,   murder   +   assault   +   rape   AS  crimes  FROM  usarrests") 이 튜토리얼에서는 학습을 위해서 익히기 쉬운 예를 위해 실제로는 유용하지 않은 것을 예로 만든 것이다. Hive는 기본적으로 많은 UDF와 column들간의 사칙연산등을 지원하고 있다. 여러분이 RHive을 이용해서 대용량 분석 작업을 할 때 만약 Hive SQL에 지원하는 기능이 이미 있고 그것으로 해결이 가능한 것이라면 UDF를 사용하기 전에 Hive SQL이 그것을 지원하는지 확인하고 그것을 이용해서 처리하는 것을 추천한다. 관련된 내용은 아래 URL에서 찾을 수 있다. https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF 만약 Hive에서 기능을 지원하지 않고 여러 컬럼들을 이용해서 복잡한 계산을 하거나 데이터마이닝(data mining)이나 기계학습(machine learning)을 위한 자질(feature) 값을 추출하는 일을 해야 한다면 RHive UDF 기능이 매우 유용할 것이다. RHive - UDAF 1 UDF와 유사한 것으로 Hive UDAF라는 것을 지원하고 있다. UDAF는 aggregation을 위한 지원(support)하기 위한 것으로 SQL구문에서 "group by"에 의해 지정된 column의 값을 키(key)로 하여 취합된 데이터들에 대해서 순차적으로 어떤 연산을 수행하게 해주는 펑션이다. 이것 또한 UDF처럼 새로운 것을 Hive에 추가하기 위해서 Java로 모듈을 작성해야
  • 10. 하지만 RHive는 이것을 R언어를 이용해 작성할 수 있도록 지원하고 있다. 설명하지는 않았지만 앞서의 예제들에서 여러분은 sumAllcolumns라는 4개의 UDAF 펑션을 이미 보았다. sumAllcolumns라는 이름으로 시작하는 펑션들은 입력된 인수의 값을 모두 더하는 일에 관련된 함수들이다. 여기서 여러분은 몇가지 의문을 가질 것이다. 첫째, "어째서 UDAF라는 기능은 4개의 펑션이 한꺼번에 필요한 것인가" 일것이고 둘째, UDAF는 어떤 것에 이용할 수 있는가" 일 것이다. 이를 이해하기 위해서는 먼저 실행코드를 보고 이해하는 것이 좋다. 먼저 UDAF용 함수들을 적용하기에 적절한 테이블을 만들기 위해서 R의 datasets에 기본 내장되어 있는 iris data를 Hive에 업로드 한다. rhive.write.table(iris)       [1]  "iris"   >  rhive.list.tables()                tab_name   1                  aids2   2                    iris   3  new_usarrests   4          usarrests       rhive.desc.table("iris")            col_name  data_type  comment   1          rowname        string   2  sepallength        double   3    sepalwidth        double   4  petallength        double   5    petalwidth        double   6          species        string      
  • 11. rhive.query("SELECT  *  FROM  iris  LIMIT  10")        rowname  sepallength  sepalwidth  petallength  petalwidth  species   1                1                  5.1                3.5                  1.4                0.2    setosa   2                2                  4.9                3.0                  1.4                0.2    setosa   3                3                  4.7                3.2                  1.3                0.2    setosa   4                4                  4.6                3.1                  1.5                0.2    setosa   5                5                  5.0                3.6                  1.4                0.2    setosa   6                6                  5.4                3.9                  1.7                0.4    setosa   7                7                  4.6                3.4                  1.4                0.3    setosa   8                8                  5.0                3.4                  1.5                0.2    setosa   9                9                  4.4                2.9                  1.4                0.2    setosa   10            10                  4.9                3.1                  1.5                0.1    setosa   iris data가 어떻게 구성되어 있는지 대략 파악할 수 있을 것이다. 이제 iris 테이블에 species 컬럼의 값이 같은 것들이 취합해서 각 column의 값들을 더하는 작업을 할 것이며 그것의 완성된 전체코드와 실행결과는 아래와 같다. sumAllColumns  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {              prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   }       sumAllColumns.partial  <-­‐  function(values)  {      values   }       sumAllColumns.merge  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {          prev  <-­‐  rep(0.0,  length(values))      }  
  • 12.    prev  +  values   }       sumAllColumns.terminate  <-­‐  function(values)  {      values   }       rhive.assign("sumAllColumns",  sumAllColumns)   rhive.assign("sumAllColumns.partial",  sumAllColumns.partial)   rhive.assign("sumAllColumns.merge",  sumAllColumns.merge)   rhive.assign("sumAllColumns.terminate",  sumAllColumns.terminate)       rhive.exportAll("sumAllColumns")       result  <-­‐  rhive.query("      SELECT   species,   RA('sumAllColumns',   sepallength,   sepalwidth,   petallength,  petalwidth)      FROM  iris      GROUP  BY  species")       print(result)            species   1          setosa   2  versicolor   3    virginica                                                                                                                                                  X_c1   1   250.29999999999998,171.40000000000003,73.10000000000001,12.29999 9999999995   2                                                       296.8,138.50000000000003,212.9999999 9999997,66.3   3                             329.3999999999999,148.7,277.59999999999997,101.29
  • 13. 999999999998 위의 실행결과에서 마지막으로 출력(print)된 결과를 보면 컬럼이 2개인 3개의 레코드를 만들어 낸 것을 볼 수 있다. 먼저 주목할 것은 rhive.query로 전달된 SQL구문안에 있는 RA()라는 펑션이다. 이것은 R() 펑션과 비슷한 것으로 R로 작성된 펑션을 UDAF로 구동시켜주는 펑션이다. RA()펑션의 return값은 모두 character type이며 하나의 값을 Hive로 전달한다. 그리고 Hive는 리턴받은 결과들을 처리하고 다시 최종적으로 RHive에 전달한다. 주의할 점의 RA() 펑션은 UDAF이므로 SQL의 GROUP BY 구문과 함께 사용해야만 한다. 이에 대한 자세한 내용은 Hive문서를 참조하라. 위에서 사용된 SQL구문을 구체적으로 설명하면 SELECT   species,   RA('sumAllColumns',   sepallength,   sepalwidth,   petallength,  petalwidth)      FROM  iris      GROUP  BY  species "GROUP BY"에 의해서 취합되는 species라는이름의 컬럼의 값들을 기준으로 모여진 데이터들끼리 연산을 따로 하는 것이다. 그리고 그 연산의 대상이 되는 컬럼들은 sepallength, sepalwidth, petallength, petalwidth이며 RA() 펑션은 인수로 UDAF로 사용될 R펑션들의 접두어(prefix)를 입력받고 그 뒤로 두 번째 인수부터 사용자가 정의한 column들을 입력 받아서 R로 작성된 UDAF함수 4개를 각각 상황에 맞게 적용하여 처리한 것이다. 그리고 GROUP BY로 지정한 column인 species의 값과 UDAF에 의해 만들어진 값을 새로운 컬럼으로 생성하여 결과를 만들어 낸 것이다. 여기서 아직 앞서의 의문이 풀리지 않았을 것이며 또 추가로 여러분은 몇개의 의문이 더 생겼을지도 모른다. 아직 설명되지 않은 것들에 대해서는 다음 절에서 설명한다. RHive - UDAF 2 이제 앞서의 예에서 만든 4개의 UDAF용 R펑션과 부족한 점을 설명할 것이다. 총 4개의 펑션이 UDAF를 위해서 만들어졌고 사용되었는데 아래와 같다. sumAllColumns   sumAllColumns.partial   sumAllColumns.merge  
  • 14. sumAllColumns.terminate   RHive 용 UDAF 펑션들은 같은 유저가 임의로 지정하는 prefix로 시작하는 4개의 펑션들로 구성되어야 하며 postfix로는 .partial, .merge, .terminate 그리고 postfix가 없는 이름을 가진 함수들로 작성되어야 한다. 이것은 RHive에 정한 naming rule로 바꿀 수 없다. 4개의 펑션이 필요한 이유는 Hive UDAF가 작동될 때 function들이 작동할 수 있는 Map/Reduce 과정에서의 포인트가 4곳이기 때문이다. foobar라는 이름으로 시작하는 UDAF 함수 4개를 만들었다고 가정하면 각 펑션별로 작동되는 곳들은 아래와 같다. foobar  -­‐  Map의  aggregation을  수행하는  곳  (정확히는  combine  단계)   foobar.partial  -­‐  Map의  aggregation  된  결과를  reduce에  전달하는  곳   foobar.merge  -­‐  Reduce의  aggregation을  수행하는  곳   foobar.terminate   -­‐   Reduce에서   최종   aggregation   된   것을   종료하는   곳 그리고 foobar와 foobar.merge는 유사한 일을 하며 이름은 상관없지만 인수는 2개를 가지고 있어야 하며 foobar.partial과 foobar.terminate도 역시 서로 비슷하며 이것들은 이름은 상관없지만 인수를 1개만 가질 수 있다. 이제 이 함수들이 어떻게 언제 작동되는지에 대한 것이 아직도 의문으로 남아 있을 것이다. 이제 이 4개의 함수들이 어떻게 서로 연결되어 작동하는지 이해하기 위해 함수들이 작동되는 흐름을 알아여 하는데 그것은 아래와 같다. foobar  -­‐  combine  aggregation  (map)   foobar.partial  -­‐  combine  return  (map)   foobar.merge  -­‐  reduce  aggregation   foobar.terminate  -­‐  reduce  terminate   여기서 combine 단계는 Hive의 설정에 따라 처리되지 않고 통과(pass)하고 모든 것을 reduce 단계에서 처리될 수도 있다. 설정을 정확하게 하지 않는다면 이 함수부분이 언제 통과하고 언제 수행되는지를 알기 어렵다. 따라서 4개의 펑션을 모두 만들어 놓는 것이 안전하다. 고급 지식과 완벽한 이해를 위해서는 Hive와 Hadoop의 문서를 참조하라.
  • 15. 완벽한 이해가 아닌 사용법만을 이해하고 싶다면 RHive를 UDAF 지원을 이용하기 위해서는 펑션을 4개 만들어야 하며 정해진 룰에 따라야 한다는 것을 기억해야 한다. RHive - UDAF 3 이제 UDAF용 4개의 펑션들의 인수들과 작동 방식에 대해서 설명할 것이다. 앞서 예제에서 만든 sumAllColumns라는 펑션들 중 sumAllColumns와 sumAllColumns.merge를 살펴보자. 두 함수내의 코드는 동일하다. sumAllColumns  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {              prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   }       sumAllColumns.merge  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {          prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   } 이 함수들은 인수를 2개를 처리해야만 하는데 첫번째 인수는 sumAllColumns와 sumAllColumns.merge함수에서 return한 값이 다시 sumAllColumns와 sumAllColumns.merge함수의 인수로 들어오는 것이다. 두번째 인수는 현재 record에 대해서 Hive가 넘겨주는 값이다. 첫번째와 두번째 인수는 실제로 모두 vector이거나 list이다. vector로 넘겨지기 때문 각각의 column들에 대해서는 SQL 구문에서 입력한 column들의 순서를 기억할 필요가 있다. 첫번째 인수로 넘겨지는 prev는 함수가 return한 값이 다시 돌아서 넘겨지는 것이므로 함수가 맨처음 실행될 때는 값이 없는 NULL 상태로 넘겨지게 된다. 그래서 함수내에서 is.null로 NULL인지 확인하고 처리한 것을 볼 수 있다.
  • 16. if  (is.null(prev))  {              prev  <-­‐  rep(0.0,  length(values))      } 이렇게 반복적으로 수행되어서 마지막에 레코드에서 return되는 값들은 sumAllColumns.partial과 sumAllColumns.terminate의 인수로 각각 넘겨진다. 두 함수의 함수내 코드는 동일하다. sumAllColumns.partial  <-­‐  function(values)  {      values   }       sumAllColumns.terminate  <-­‐  function(values)  {      values   } 이 두 함수들은 반복적으로 수행되지 않으며 그 때문에 인수를 하나만 받을 수 있다. 그리고 4개의 함수중에 가장 마지막에 실행되는 sumAllColumns.terminate가 return한 값은 Hive로 전달되며 하나의 column의 값으로 만들어진다. 위 예제에서는 각각 2개씩의 함수들이 동일한 코드를 가지고 있는 것을 볼 수 있는데 이 튜토리얼에서는 이것 역시 설명을 위한 쉬운 예제를 만든 것으로 실제 사용할 때는 사용자에 의해서 4개의 펑션이 모두 다른 코드를 가질 수도 있다. 그래서 함수내의 코드가 동일하다고 해도 항상 4개의 함수가 있어야 한다. RHive - UDTF 이제 앞의 예에서 작성한 코드의 결과값을 좀더 우아하게(graceful)하게 고치려고 한다. character(string)값 하나로 나오는 것은 다루기가 매우 힘들기 때문이다. 이것을 분해할 필요가 있으며 이를 위해서 RHive가 지원하는 UDTF 펑션인 unfold를 사용할 것이다. 그 결과가 앞서 예에서 SQL 구문을 실행한 결과이다. print(result)            species   1          setosa  
  • 17. 2  versicolor   3    virginica                                                                                                                                                  X_c1   1   250.29999999999998,171.40000000000003,73.10000000000001,12.2999 99999999995   2                                                       296.8,138.50000000000003,212.999999 99999997,66.3   3                             329.3999999999999,148.7,277.59999999999997,101.2 9999999999998   위에서 2번째 컬럼인 X_c1은 UDAF에 의해서 만들어진 값이며 character type으로 되어 있다. 그리고 값으로는 수치값들이 "," 로 구분되어 있음을 알 수 있다. 이것을 다시 numeric vector로 만들기 위해서는 strsplit과 같은 R 내장함수를 이용해야 하는데 record수가 적을 때는 문제가 없지만 record 수가 많다면 처리하는데 문제가 발생한다. 위의 예에서는 레코드수가 고작 3개이지만 크기가 큰 테이블에 비슷한 처리를 할 때는 record수가 3,000,000개가 넘을 수도 있다. 따라서 UDAF가 return한 값은 구분되어 각각의 column값으로 만들어져야 한다. 이것을 위해서는 subquery와 UDTF가 필요하며 UDTF를 사용해서 수정된 코드는 아래와 같다. sumAllColumns  <-­‐  function(prev,  values)  {      if  (is.null(prev))  {              prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   }       sumAllColumns.partial  <-­‐  function(values)  {      values   }       sumAllColumns.merge  <-­‐  function(prev,  values)  {  
  • 18.    if  (is.null(prev))  {          prev  <-­‐  rep(0.0,  length(values))      }      prev  +  values   }       sumAllColumns.terminate  <-­‐  function(values)  {      values   }       rhive.assign("sumAllColumns",  sumAllColumns)   rhive.assign("sumAllColumns.partial",  sumAllColumns.partial)   rhive.assign("sumAllColumns.merge",  sumAllColumns.merge)   rhive.assign("sumAllColumns.terminate",  sumAllColumns.terminate)       rhive.exportAll("sumAllColumns")       result  <-­‐  rhive.query(      "SELECT   unfold(dummytable.dummycolumn,   0.0,   0.0,   0.0,   0.0,   ',')                          AS   (sepallength,   sepalwidth,   petallength,   petalwidth)        FROM  (            SELECT   RA('sumAllColumns',   sepallength,   sepalwidth,   petallength,  petalwidth)  AS  dummycolumn            FROM  iris            GROUP  BY  species            )  dummytable")       print(result)      sepallength  sepalwidth  petallength  petalwidth   1              250.3            171.4                73.1              12.3   2              296.8            138.5              213.0              66.3  
  • 19. 3              329.4            148.7              277.6            101.3   SQL문이 다소 복잡해 졌으나 최종결과에서 UDAF가 return값이 모두 unfold라는 UDTF에 의해서 각각의 column들로 분리되어 만들어진 것을 볼 수 있다. unfold는 RHive에 지원하는 UDTF 함수이며 R코드를 따로 적용할 필요는 없다. 그리고 Hive의 UDTF는 현재 제약으로 인해 SELECT절에 다른 구문을 넣을 수 없다는 단점이 있다. 이것은 RHive에서는 해결할 수 없는 것으로 Hive의 기능이 개선될 때까지 기다려야 할 것이다. 지금까지의 UDF, UDAF, UDTF는 SQL구문을 이용해서 1단계 Map/Reduce로 작업이 처리되도록 한 것이다. 만약 여러분이 RHive를 이용해서 매우 복잡한 작업을 하려고 한다면 여러 단계의 Map/Reduce가 필요 할 수 있다. 이것은 일반적인 Map/Reduce 구현체(implementation)이나 Hadoop streaming 구현체에서 흔히 볼 수 있는 것이다. 이런 여러 단계의 Map/Reduce를 결합해서 작업을 하려고 한다면 중간 결과를 저장하기 위한 임시 테이블을 만들어 두고 결과를 저장한 후 삭제하는 작업을 해야 할 수 있다.