업무상 데이터분석가분들과 업무를 자주 하게 되는데 아무래도 주력이 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 |