본문 바로가기
빅데이터/hive

[hive] 작은 사이즈의 파일 머지 설정과 그로 인한 오버헤드

by hs_seo 2019. 2. 20.

하이브에서 FROM INSERT 문을 이용하여 한번에 여러곳에 데이터를 입력할때 다음과 같이 사용합니다.

[FROM INSERT 문을 이용한 입력 예시]

FROM ( SELECT * FROM tbl )
INSERT tableA
INSERT tableB


[TEZ 엔진 실행 결과]

----------------------------------------------------------------------------------------------
        VERTICES      MODE        STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED 
----------------------------------------------------------------------------------------------
Map 1 .......... container     SUCCEEDED     13         13        0        0       0       0 
Map 2 .......... container     SUCCEEDED      1          1        0        0       0       0 
----------------------------------------------------------------------------------------------
VERTICES: 02/02  [==========================>>] 100%  ELAPSED TIME: 712.86 s  
----------------------------------------------------------------------------------------------


이때 최종적으로 생성되는 파일의 개수는 매퍼의 개수인 13개입니다. 각 테이블의 위치마다 13개씩 총 26개의 파일이 생성됩니다.


만약 매퍼의 수가 많아진다면 그만큼의 파일이 생성되고 이는 HDFS에 부담이 됩니다. 따라서 파일의 개수를 줄이기 위해 적당한 크기의 파일로 묶는 머지 작업을 추가 하게 됩니다.


[32MB 보다 작은 파일을 모아서 256MB 파일로 묶음]

set hive.merge.mapfiles=true;
set hive.merge.mapredfiles=true;
set hive.merge.tezfiles=true;
set hive.merge.size.per.task=256000000;
set hive.merge.smallfiles.avgsize=32000000;


파일 머지 작업은 파일의 개수를 줄여서 HDFS의 부담을 줄일 수 있지만, 작업에 따라 시간이 오래 걸릴 수 있습니다.

1KB의 파일이 3000~4000 개씩 생성되었을 때 이 파일을 하나로 묶는 작업에 시간이 많이 걸리기 때문입니다.


이때는 hive.optimize.sort.dynamic.partition 옵션을 true로 설정하면 하이브에서 내부적으로 다이나믹 파티션의 데이터를 정렬하여 줍니다. 이 설정으로 리듀서 작업이 생성되고 이 작업에서 파일을 묶어 줍니다.

[hive.optimize.sort.dynamic.partition 옵션 설정]
set hive.optimize.sort.dynamic.partition=true;

----------------------------------------------------------------------------------------------
        VERTICES      MODE        STATUS  TOTAL  COMPLETED  RUNNING  PENDING  FAILED  KILLED 
----------------------------------------------------------------------------------------------
Map 1 .......... container     SUCCEEDED     13         13        0        0       0       0 
Map 6 .......... container     SUCCEEDED      1          1        0        0       0       0 
Reducer 2 ...... container     SUCCEEDED      2          2        0        0       0       1 
Reducer 3 ...... container     SUCCEEDED      2          2        0        0       0       2 
Reducer 4 ...... container     SUCCEEDED      4          4        0        0       0       0 
Reducer 5 ...... container     SUCCEEDED      4          4        0        0       0       0 
----------------------------------------------------------------------------------------------
VERTICES: 06/06  [==========================>>] 100%  ELAPSED TIME: 893.55 s  
----------------------------------------------------------------------------------------------

[셔플 작업 오류시 설정]
set mapreduce.reduce.shuffle.memory.limit.percent=0.5;

하지만 이 소트 작업을 추가하면 리듀서 하나가 매우 오래 동작하는 문제점이 발생할 수 있습니다. 리듀서 하나로 정렬을 수행하여 시간이 많이 발생하는 것으로 추정됩니다. 또는 셔플과정에서 메모리 힙 오류가 발생할 수 있는데 이때는 설정을 추가하여 버퍼보다 로컬 디스크에 빨리 쓰게 하여 해결할 수 있습니다. 

결론적으로 하이브는 맵퍼 단독(mapper only)작업 일때는 매퍼의 개수만큼 파일이 생성되고, 이때 작은 사이즈의 파일이 여러개 생성되어 문제가 발생하면 리듀서 작업이나 파일 머지 작업을 추가하여 해결할 수 있습니다. 리듀서 작업의 추가는 아래와 같이 INSERT 시에 임의의 칼럼에 SORT BY를 추가하는 것입니다. 데이터가 단 하나인 컬럼도 괜찮습니다. 

SORT BY로 인하여 데이터를 리듀서로 모으고 이는 머지작업을 추가하지 않아도, 머지하는 것과 동일한 효과를 줄 수 있습니다. 여기에 머지를 추가하면 머지 작업의 효율이 매우 좋아집니다. 

FROM ( SELECT * FROM tbl )
INSERT tableA SORT BY col1
INSERT tableB SORT BY col2


반응형