티스토리 뷰

반응형

복잡한 스키마를 비슷한 목적에 맞게 그룹핑하고 관리하기 위해서 struct 로 필드를 관리할 필요성이 생긴다.

이런 작업은 보통 스키마레지스트리를 통해 관리하고, 데이터를 가공해서 적재할때 default 값에서 일부값만 변경하여 재적재 하고 싶은 경우가 생길수 있다. 하지만 struct 에서 일부값만 바꾸는 기능이 없다.

 

그래서 개밥먹기로 만들어서 구현했다.

hive 3.x 버전 기준으로 빌드했고 hive 4.x 에서도 동작하는데는 큰 무리가 없을것으로 보인다.

 

GenericUDF 를 만들면서 삽질기

사실 처음에 struct 의 리턴값을 List<List...> 형태로 만들면 named_struct 함수로 테스트할때 잘 동작했는데,

orc 포맷의 테이블에서 사용할때는 내부적으로 OrcStruct 클래스를 사용해서 만들어 져서 실패나서 난감했었는데 여기서 내가 처음 만들어 보다보니 노하우가 없어서 그랬던것었다.

Error: Unable to get the next row set with exception: org.apache.hadoop.hive.ql.metadata.HiveException: Error parsing json: org.apache.hadoop.hive.ql.io.orc.OrcStruct cannot be cast to org.apache.hadoop.io.Text (state=,code=0)

 

기본적으로 데이터를 추출할때는 DefferdObject[] 의 값을 get() 한 값을 활용할때, Inspector 를 통해 대입하고 가져와야 문제없이 변환이 가능했던 점이었다. 이 부분은 나중에 따로 포스팅하도록 하고 여기서는 struct 의 일부값만 변경하는 기능을 만들어뒀고 사용할 수 있다! 라는 것만 이해해 두자.

struct 의 일부값만 변경하기 : set_value

hive 의 기본 UDF 가 아니라 내가 필요해서 만든 UDF 이다. struct 타입만 지원하고, 변경하고자하는 노드는 PRIMITIVE 타입만 지원하도록 구현을 해두었다. 대신, 하나의 struct 에서 N개의 값을 변경할 수 있도록 처리했으니 여러개의 값도 변경이 가능하다.

덤으로 struct 의 struct 도 지원하기 때문에 "키.키2" 형태로 나열식으로 표현하면 된다.

https://github.com/jungkoo/hive3-udf/issues/1

hive3-udf-1.0.jar
0.05MB

 

사용방법

가장 기본적인 사용은 아래와 같다. struct필드는 필드명이 될수도 있고, named_struct() 를 이용해 사용자가 만들어낸 값이 될 수 도 있다. 키값은 struct 의 key 값을 의미하며, 1depth 를 넘어가서 찾아야 한다면 . 를 구분자로 연결한 키값을 사용하면 된다. 

set_value(struct필드, 키값, 변경할 값)

만약, 더 많은 값을 한번에 변경해야 한다면? 값을 나열식으로 계속 넣어주면 된다.

set_value(struct필드, 키1, 값1,    키2, 값2, ... 키n, 값n )

 

예제

사실 사용법을 열심히 말해도 예제를 보는게 더 이해가 빠를테니 예제를 확인해보자

beeline> add jar hdfs://..생략.../hive3-udf-1.0.jar;

beeline> CREATE TEMPORARY FUNCTION update_value as 'org.apache.hadoop.hive.ql.udf.generic.GenericUDFUpdateValue';

-- {"name": "gildong", "age": 18, "info"; {"city": "seoul", "cnt": 1}}
beeline> with sample as ( 
 select named_struct(
    'name', 'gildong', 
    'age', 18, 
    'info', named_struct(
       'city', 'seoul',
       'cnt', 1 
    )) as f1 )

-- info.cnt 값을 2로 변경 (기존값 1)
select f1, update_value(f1, 'info.cnt', 2) as f2 from sample;
+----------------------------------------------------+----------------------------------------------------+
|                         f1                         |                         f2                         |
+----------------------------------------------------+----------------------------------------------------+
| {"name":"gildong","age":18,"info":{"city":"seoul","cnt":1}} | {"name":"gildong","age":18,"info":{"city":"seoul","cnt":2}} |
+----------------------------------------------------+----------------------------------------------------+


-- info.cnt , info.city 값을 동시에 바꾸려면? 아래와 같이 나열하면 된다.
-- select update_value(f1, 'info.cnt', 2, 'info.city', 'busan');

 

hive query 만으로 많은걸 하려고 하니 UDF 를 직접 만들게 되는것 같다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함