데이터 엔지니어링/HIVE

[Hive] 하이브 Query 주의 사항

안용감한호랑이 2023. 10. 25. 00:42

업무상 데이터분석가분들과 업무를 자주 하게 되는데 아무래도 주력이 Python이신 분들이 많다 보니

쿼리 사용에 미숙한 채로 Workflow를 개발하여 3~4시간 동안 서버의 cpu, memory를 전부 잡아먹는 배치를 만드는 경우가 잦아 쿼리 튜닝 중 자주 발생하는 문제점 몇 가지 주의사항을 공유하겠습니다.

 

 

1. 조건절 내부 사용자 정의함수(UDF) 제거

  • Hive 버전마다 상이하긴 하지만 UDF를 조건절에 사용하는 경우 optimizer가 제대로 된 실행계획을 작성하지 못하는 경우가 발생합니다. 따라서 UDF를 최대한 피하는 방향으로 쿼리를 작성하여야 합니다.

 

2. Partition column의 조회

  • Partition column을 substring 등으로 변경하지 않는다.
  • Partition의 경우 대부분 날짜를 사용하는데 일별 파티션을 월로 조회하기 위해 substring 등의 함수를 사용하는 경우 Hive는 Partition pruning이 진행되지 않아 테이블을 partition으로 분할하는 의미가 없어집니다. 

 

3. count(distinct 컬럼) 

  • 조금 유명한 사례인데 distinct 사용 시 하나의 리듀스에서 해당 작업을 맡아 처리하기 때문에 데이터의 건수와 상관없이 1개의 리듀스만 할당하여 분산처리를 하지 못한다.
  • 데이터가 크다면 group by를 권장한다.
  • 위와 같이 많은 블로그, 대기업 테크 블로그에서 말하고 있어 46억 건(약 1TB) 데이터로 테스트하였으나 컨테이너 할당 속도, 네트워크 속도를 고려했을 때 min ~ max 차이가 5초 이내로 큰 차이를 확인하지 못하였습니다.
  • 다만 위와 같은 경우도 존재하니 count와 distinct를 같이 사용하기보단 group by를 이용한다.

 

4. Join 사용 시 고려사항

  • 가장 큰 테이블이 쿼리의 가장 마지막 순서로 오도록 해야 한다.
    • Hive optimizer는 쿼리의 마지막 테이블이 가장 크다고 가정하기 때문에 해당 가정으로 수행계획을 작성한다.
    • 다만 쿼리의 마지막에 넣기 힘든 경우 힌트를 사용한다.
    • /*+ STREAMTABLE(테이블명) */
  • OUTER JOIN과 PARTITION 필터의 순서 고려
    • OUTER JOIN은 WHERE 조건 절의 파티션 필터를 무시한 채 진행한다.
    • 즉 JOIN을 수행한 후 WHERE 절을 계산하기 때문에 테이블의 사이즈가 크다면 상당한 리소스가 필요하다.
-- 01.
-- OUTER JOIN과 파티션 필터의 순서가 고려되지 않은경우
-- TABLE_1과 TABLE_2 전체 테이블이 CONDITION 컬럼으로 JOIN된 이후
-- WHERE절의 PARTITION조건의 필터를 수행한다.
SELECT
	A.COLUMN_NAME
      , B.COLUMN_NAME
FROM	TABLE_1 A
LEFT OUTER JOIN TABLE_2 B
ON	A.CONDITION = B.CONDITION
WHERE	1=1
AND	A.PARTITION = 'A_VALUE'
AND	B.PARTITION = 'B_VALUE'
;

-- 02.
-- OUTER JOIN과 파티션 필터의 순서가 고려된 경우
-- TABLE_1과 TABLE_2 테이블은 각각 파티션 필터에의해
-- PARTITION PRUNING이 진행되며
-- 이후 JOIN을 수행한다.
SELECT
    A.COLUMN_NAME
  , B.COLUMN_NAME
FROM(
    SELECT
            COLUMN_NAME
          , CONDITION
    FROM    TABLE_1
    WHERE   1=1
    AND     PARTITION = 'A_VALUE'
) A
LEFT OUTER JOIN(
    SELECT
            COLUMN_NAME
          , CONDITION
    FROM    TABLE_2
    WHERE   1=1
    AND     PARTITION = 'B_VALUE'
) B
ON  A.CONDITION = B.CONDITION
;

 

5.  Asterisk(*) 미사용

  • 대규모 데이터의 경우 *보다 필요 컬럼만 사용할 것
    • Hive에서 자주 사용하는 ORC, parquet 파일은 column단위로 파일을 저장한다. 즉 컬럼을 명시하지 않는다면 모든 파일을 불러오게 된다.
    • 이러한 쿼리는 mr엔진에서는 불필요한 File I/O를 발생시키며 tez에서도 불필요한 메모리 사용을 유발한다.

 

6. Dynamic partition(동적 파티션)

  • Dynamic partition이란 INSERT문 수행 시 partition을 지정하지 않고 값에 따라 적재하도록 하는 방법입니다.
  • 이러한 동적 파티션 할당은 정적 파티션보다 매우 느리고 메모리를 많이 사용하게 됩니다.
  • 월 배치등의 경우 파라미터 등을 통해 파티션을 지정할 수 있는 경우 파티션을 지정할 수 있도록 합니다.

'데이터 엔지니어링 > HIVE' 카테고리의 다른 글

[Hive]하이브 관련 튜닝 옵션 정리  (1) 2023.10.24
[Hive] Hive-맵리듀스(2)  (0) 2023.08.09
[Hive] Hive-Intro-(1)  (0) 2023.08.09
[Hive] Hive-시작-(0)  (1) 2023.08.08