ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Hive] 하이브 핵심정리
    [IT] 공부하는 개발자/Data engineering 2023. 10. 19. 19:30

     

    하이브 개요

    하이브는 하둡의 HDFS 데이터를 SQL로 질의할 수 있게 해주는 Hadoop 생태계의 일원이다.
     
    하이브는 테이블(Table), 파티션(Partition), 버킷(Bucket) 세 개의 구조로 분할될 수 있다. 테이블을 HDFS 디렉토리에 대응시키고, 이를 파티션으로 분할 후 파티션을 버킷으로 차례차례 나눌 수 있다.
     


     

    하이브의 장점

    • 하이브의 HQL은 SQL과 문법이 비슷하다.
    • 하이브는 여러 컴퓨팅 프레임워크에서 동작할 수 있다. (MapReduce, Spark, ...)
    • 하이브는 HDFS 데이터에 Ad-hoc 질의를 할 수 있다.
    • 하이브는 UDF, 사용자 정의 I/O 포맷을 지원한다.

     


     

    하이브의 구조

    테이블

    테이블 = 디렉토리에 맵핑된다고 생각하면 된다.
    하이브에서 salary 테이블을 생성하면 HDFS에서 /user/hive/warehouse/salary 디렉토리가 생성된다.
     
    만약 이미 HDFS에 데이터를 가지고 있다면, 이 데이터를 설명하는 EXTERNAL HIVE table을 생성할 수도 있다.
    EXTERNAL 테이블의 가장 큰 장점은 실수로 테이블과 함께 데이터를 삭제되거나 조작되는 것을 방지할 수 있다는 것이다. 데이터를 내부 테이블에서 유지한다면 하이브가 테이블과 데이터의 모든 생명주기를 관리하기 때문에, 테이블이 삭제되면 데이터도 삭제된다. 하지만 EXTERNAL 테이블은, 메타데이터 테이블이 hive에 삭제되더라도 데이터는 보존된다.
     

    파티션

    파티션은 HDFS 테이블의 데이터를 물리적으로 분할함으로써, 쿼리가 스캔하는 데이터의 양을 제한하여 성능을 향상하는 것이다.
     
    파티션이 없다면 모든 하이브 테이블을 스캔하게 되므로 성능 저하가 발생할 수 있다. 하지만 파티션이 포함된 쿼리를 사용하면, 해당 파티션의 디렉토리에 찾아가 그 데이터만 쿼리 할 수 있으므로 성능을 크게 개선할 수 있다.
     
    파티션이 정의된 테이블에 데이터를 추가할 때에는, 파티션 칼럼을 명세해야 한다.
    정적 파티션의 경우, static value를 명세해야 하지만, 동적 파티션의 경우에는 쿼리에 static 한 partition value를 주입하지 않아도 된다. 동적 파티션은 데이터 크기가 크고, 파티션 값이 무엇이 될지 모를 때 유용하다.
    예를 들어 주로 '날짜' 칼럼이 동적 파티션으로 사용될 수 있다.
    예시) dt=20231019 / hr=07
     

    SET hive.exec.dynamic.partition=true

     
     
    Hive는 최소 1개 이상의 정적 파티션을 명세하는 것이 default인데, 이 제약을 비활성하려면 다음과 같이 설정해야 한다.
     

    SET hive.exec.dynamic.partition.mode=nonstrict

     

    버킷

    버킷은 데이터 집합을 작은 부분으로 다시 잘게 나누는 또 다른 기술이다.
    더 쉽게 요약하자면,
    파티션 = 데이터를 디렉토리로 나누어 저장
    버킷 = 데이터를 파일로 나누어 저장 (해시 처리)
    하는 기술이다.
     
    버킷 개수를 적절하게 정의해야 효율을 극대화할 수 있다. 보통은 블록*2으로 설정한다고 한다(하둡의 블록 크기가 256MB라면, 버킷에 512MB를 설정하는 것이다. 그러면 한 버킷에 파일이 2개 생길 것이다.). 가능하면 2의 제곱 숫자를 사용하는 것이 권장된다.
     


     

    뷰 View

     
    하이브의 뷰는 데이터를 저장하거나, 실체화된 데이터를 갖지 않는다.
    READ ONLY이며, 쿼리를 간단히 만들어 쓰기 위한 것이다.
    뷰의 스키마는 뷰를 만드는 순간 고정된다. 만약 뷰를 만들고 나서, 뷰가 참조하는 기본 테이블 스키마가 변경되더라도 그것은 뷰의 스키마를 바꾸지 않는다. (만약 기본 테이블 스키마나 데이터가 뷰가 참조할 수 없는 형식으로 변경된다면, 뷰의 모든 쿼리는 실패한다.)
     
    뷰를 생성할 때에는 MapReduce 잡이 실행되지 않는다. 쿼리 할 때에는 MapReduce 잡이 실행된다.
     
     


     

    쿼리

    테이블 조인

     
    여러 테이블 간의 조인을 수행할 때에, HDFS의 데이터를 처리하기 위해 MapReduce작업이 생성된다. 
    각각의 작업은 Stage라고 부른다.

    1. Mapper Stage : 맵 단계에서 매퍼는 테이블을 읽고 조인 칼럼 값을 키로 정해 출력한다. 키 — 값 쌍을 중간 파일에 기록한다.
    2. Shuffle Stage : 셔플 단계에서 이러한 쌍을 정렬하고 병합한다. 동일한 키의 모든 행을 동일한 리듀스 인스턴스로 전송한다.
    3. Reduce Stage : 리듀스 단계에서 리듀서는 정렬한 데이터를 가져와 조인을 수행한다.


    이때 퍼포먼스 향상을 위해 큰 테이블을 JOIN 문 오른쪽에 두어야 한다. (JOIN 문의 마지막 테이블이 Reducer를 통해 스트림 되기 때문이다. 큰 테이블을 기준으로 스트리밍하면, 큰 테이블을 매번 처음부터 끝까지 읽지 않아도 된다. 큰 테이블은 블럭 단위로 끊어서 읽게 되고, 작은 테이블들은 리듀서의 메모리에 버퍼된다.)


     
    또한 하이브에는 기본 JOIN (INNER, OUTER, LEFT 등) 외에 MAPJOIN이라고 하는 특수 조인이 있다. MAPJOIN은 Reduce를 하지 않는 조인이다. 작은 테이블을 테이블화하여 메모리에 올려서 Mapper 단계에서 바로 조인을 시켜버리는 것이다. MapReduce 에서 가장 비싼 스테이지인 Shuffle과 Reduce가 생략되기 때문에 성능이 개선된다. 대신 MAPJOIN을 사용하면 UNION ALL, GROUP BY/JOIN/SORT BY 뒤에 사용할 수 없는 제약이 있다.

     

     


     
    Usecase of MAPJOIN

    • 작은 테이블을 조인할 때 성능 향상을 위해 사용됩니다.
    • 두 테이블의 조인 조건이 단일 칼럼에 대해 동일한 값을 가질 때 사용됩니다.
    • 작은 테이블이 메모리에 들어갈 만큼 작을 때에만 수행할 수 있다.

     
    즉 두 테이블을 조인하고자 할 때, 한 테이블이 비교적 몹시 작으면 MAPJOIN을 쓰는 것이 유리하고 그렇지 않으면 INNERJOIN을 써서 MapReduce로 성능개선을 꾀하는 것이 낫다.

     

    만약 아래 옵션이 활성화되어 있다면, Hive 는 자동으로 조인을 최적화한다. 작은 테이블이 25MB(default) 이하라면 하이브는 Map Join 이나 Streaming Join 을 자동으로 시도할 것이다.

     

    hive.auto.convert.join=true;


     
     

    ORDER와 SORT

    하이브에서 사용되는 정렬 키워드는 ORDER BY이다.
    주의하자, ORDER BY로 하나의 Reducer만 사용하여 전역 정렬을 수행하면 리턴 시간이 더 많이 소요된다. 따라서 ORDER BY를 사용할 경우 LIMIT을 명세해주어야 한다.
     
    SORT BY는 데이터를 리듀서로 보내기 전에 정렬을 완료하는 것이다. 이때에 Reducer 개수가 1개로 설정되어있지 않다면, 각 리듀서에서만 내부 정렬을 수행한다. 전체 데이터를 순서는 보장하지 않지만, 각각의 reducer내의 데이터의 순서는 보장되며 훨씬 빠른 성능으로 정렬할 수 있다.
     

    SET marped.reduce.tasks = 1;

     

    트랜잭션

    하이브는 0.13.0 버전 이전에는 Row level 단위의 트랜잭션을 지원하지 않았다.
    0.13.0 버전 이후에 한해, ORC 파일 데이터 혹은 버킷 테이블의 데이터 한정으로만 ACID 트랜잭션을 지원한다.
     


     

    사용/성능 고려 사항

     
    COUNT와 DISTINCT를 동시에 사용하지 말 것
    이 경우 하이브는 환경 설정에 적용된 리듀스 작업 개수(marped.reduce.tasks = 20)를 무시하고 하나의 리듀스만 사용하게 되고, 그 경우 바틀넥으로 이어질 수 있다.
    대신 다음과 같이 서브 쿼리를 써야 한다.
     

    # ASIS
    SELECT count(distinct employees.employee_id) FROM company;
    
    # TOBE
    SELECT count(*) FROM (SELECT distinct employees.employee_id FROM company) a;

     
     
    COALESCE의 적극적 사용
    하이브는 칼럼 값이 NULL인 로우를 집계할 때 무시해 버린다. 로우를 드롭하지 않고 사용하게 하려면, 칼럼 값이 NULL 일 때 기본값을 할당하는 COALESCE를 사용하자.
     

    SELECT coalesce(employee.id, employee.name) FROM company;

     
     
    샘플링
    데이터 크기가 매우 커서 샘플링을 하는 경우, 적절한 샘플링 방식을 선택하자. 하이브는 Random sampling, Bucket table sampling, Block sampling 3가지 샘플링 방식을 제공한다.
     
    랜덤 샘플링 = RAND(), LIMIT을 이용하여 Random row를 뽑아서 샘플링. 데이터를 Block 단위로 나누고, 각 block에서 일정 비율의 데이터를 무작위로 선택하는 것이다. 샘플 데이터의 절대 숫자가 적다면(block, bucket 단위와 비교하여) 랜덤 샘플링이 가장 균일한 데이터를 취득할 수 있다.
    버킷 테이블 샘플링 = 블록 테이블에 최적화된 샘플링 방법. 
    블록 샘플링 = HDFS 블록 단위로 샘플링하는 것. 데이터가 클 때에 빠른 샘플링을 하기에 유리하다.
     
     
    쿼리 실행 계획
    EXPLAIN 커맨드를 사용하면 쿼리 실행 계획을 리턴할 수 있다.
     
     
    설계 최적화 - 파티셔닝
    큰 테이블에서, 파티션으로 데이터를 물리적으로 구분하는 것은 쿼리의 성능을 개선할 수 있는 가장 효율적인 방법이다. 파티션의 선정은 데이터를 균일하게 분리할 수 있는 칼럼으로 하는 것이 좋다.
    - 일반적으로 날짜와 시간으로 파티션을 많이 사용한다. 연도, 달, 일, 시간 모두 사용할 수 있다.
    - 비즈니스 로직으로 구분된 파티션. 데이터를 균등하게 분리할 수 있는 키가 있다면 그것으로 사용해도 좋다.
     
    버켓팅
    버킷 키가 있으면 샘플링 시 버킷 테이블 샘플링을 사용하여 속도를 높일 수 있다.
     
    인덱스
    RDB에서 특정 칼럼을 해시하여 인덱스를 사용하듯, 하이브에서도 인덱스를 사용할 수 있다. 인덱스 생성 시 하이브는 인덱스에 대한 새로운 인덱스 테이블을 생성한다.
     
    파일 포맷
    하이브는 TEXTFILE, SEQUENCEFILE, RC, ORC, PARQUET 등의 파일 포맷을 지원한다.
    이 중 ORC, PARQUET 이 빅데이터에 가장 효율적인 포맷으로 알려져 있다. 앞의 3가지와 비교하여 블록 사이즈가 50배 가까이 크다.
     
    ORC

    • 칼럼 단위 압축으로 대규모 쿼리에 최적화
    • Default BLOCK size: HDFS를 따라간다, 128~256MB
    • Hive ACID transaction 지원하는 포맷으로, Hive에 최적화

     

    PARQUET

    • 칼럼 단위 압축으로 대규모 쿼리에 최적화
    • Default BLOCK size: HDFS를 따라간다, 128~256MB
    • 하둡 생태계의 프로젝트를 넓게 지원한다.

     


    Reference

    하이브 핵심 정리 (에이콘)

    https://towardsdatascience.com/apache-hive-optimization-techniques-2-e60b6200eeca


    - 공부 후 잊어버리지 않기 위한 요약 포스팅입니다

    댓글

Copyright in 2020 (And Beyond)