Data Engineering/Hive

[Hive] Bucketing & Table Sampling

keyhong-DE 2023. 12. 14. 23:18

Bucketing

큰 데이터를 더 관리하기 쉬운 작은 데이터 셋들로 분해하는 기술이다.

  • 하나의 컬럼에 버켓팅 하면 만들고자하는 버켓의 개수에 따라 동일한 해쉬 값(컬럼 값에 Hash Function을 적용하여 만들고자 하는 버켓 개수로 나누면 Hash Index를 얻는다.)을 가진 레코드가 각각의 버켓으로 이동한다.
  • 버켓팅을 단독으로 쓸 수도 있지만, 파티셔닝과 함께 사용하면 최고의 성능을 발휘한다. 하지만 그렇지 않은 경우도 있다. 예를 들어 500개의 레코드에 100개의 고유한 부서가 있을 경우, 파티셔닝을 하면 100개의 파티션이 만들어진다. 이런 경우 파티셔닝을 최적화에 도움이 되지 않는다.
  • 파티션(디렉터리)과 달리 버켓은 실제 물리적인 파일이다.
  • ☆ 데이터 셋에 따라 버켓 수를 명시적으로 설정할 수 있고 제어할 수 있다.
  • Map Join을 할 때 퍼포먼스 향상에 도움이 된다. 두 테이블 모두 버켓이 된 해당 열을 기준으로 조인이 수행되는 경우 매퍼와 일치하는 행의 위치를 정확히 알 수 있다. (탐색 시간 절약 + 데이터의 작은 부분만 조인 처리)
  • 단, 버켓 조인을 하려면 두 테이블 모두 같은 컬럼에 대해 버켓팅이 되어 있어야 하고, 테이블의 버켓의 수가 같아야만 한다.
  • ☆ 한계 : 데이터가 테이블에 제대로 로드 되었는 지 여부는 보장되지 않는다. 버켓에 로드되는 데이터를 직접 확인해야 한다.

버켓팅 활성화하기

SET hive.enforce.bucketing = true;
SET hive.exec.dynamic.partition.mode = nonstrict;

Query

-- 파티셔닝 + 버켓팅 테이블 생성하기
CREATE TABLE IF NOT EXISTS dept_buck (
    dept_no int,
    empname string,
    sal int,
    location string
)
PARTITIONED BY (deptname string)
CLUSTERED BY (location) INTO 4	BUCKETS
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;

-- 데이터 적재하기
INSERT INTO TABLE dept_buck
PARTITION (deptname)
SELECT col1, col3, col4, col5, col2
FROM dept_with_loc;

Table Sampling

일반적인 샘플링은 하나의 파티션 안의 하나의 버켓에서 데이터를 꺼낸다. 이렇게 얻는 데이터는 제한적인 정보를 가진다. 버켓팅을 통해 데이터의 값에 따라 여러 버켓으로 나누었을 때, 일반적인 샘플링은 선발되는 데이터가 각 계층을 대표하지 못하기 때문이다. 이러한 문제를 해결하기 위해 Table Sampling을 사용한다.

 

Table Sampling은 여러 버켓에서 분산 방식으로 데이터를 골고루 수집한다. Table Sampling은 버켓 열이 아닌 경우에도 모든 열에서 수행할 수 있지만, 그 경우 전체 테이블 스캔을 한 후에 샘플을 가져온다. 전체 테이블 스캔은 시간이 오래 걸리는 고비용의 트랜잭션이므로 버켓 열에서 테이블 샘플링 하는 것이 더 좋다.

-- 해당 데이터 셋은 균일하게 되어 있지 않다.
SELECT * FROM dept_buck LIMIT 10;

-- 4개의 버켓을 각각 2개의 버켓 그룹으로 나눈다. 그 다음, 모든 그룹의 첫 번째 버켓을 선택한다.
SELECT deptno, empname, sal, location FROM dept_buck TABLESAMPLE ( BUCKET 1 OUT OF 2 ON LOCATION );

-- 4개의 버켓을 3개의 버켓 그룹으로 나누면 더 적은 데이터를 발생한다.
SELECT deptno, empname, sal, location FROM dept_buck TABLESAMPLE ( BUCKET 1 OUT OF 3 ON LOCATION );

백분율이나 데이터 사이즈, 행의 수와 같이 다른 매개변수를 이용하여 샘플링을 하는 것도 가능하다.

-- 각 입력 분할에서 2% 개의 데이터를 표출한다. 
SELECT deptno, empname, sal, location FROM dept_buck TABLESAMPLE (2 PERCENT);

-- 각 입력 분할에서 1MB 만큼의 데이터를 표출한다. 테이블 사이즈가 지정된 용량보다 작을 경우, 전체를 표출한다.
SELECT deptno, empname, sal, location FROM dept_buck TABLESAMPLE (1M);

-- 각 입력 분할에서 10개의 행을 선택하여 표출한다.
SELECT deptno, empname, sal, location FROM dept_buck TABLESAMPLE (10 rows);