Hive에서 제공하는 기능중에서 일반 SQL 에서는 볼 수 없는 기능들 중, 리듀서에 보내는 데이터를 분류할 수 있는 3가지가 있다.
우리가 SQL에서 자주 보던 order by 와 함께 하이브 정렬은 order by, sort by, distribute by, cluster by 총 네가지 종류가 있다.
아래 그림을 보면서 이해해보자.
링크를 참고하였다.
모든 데이터를 정렬하여 하나의 파일로 생성한다. 데이터가 클 경우 시간이
오래 걸리고, Out of Memory 오류가 발생할 수 있다. 데이터가 작을 때 사용 하는 것이
좋고 데이터가 클 경우 limit 옵션을 이용하여 처리 개수를 제한 하는 것이 좋다.
즉, Map-Reduce가 끝난 뒤 최종적으로 모인 하나의 리듀서에서 정렬을 하기 때문에 정확히 정렬된 결과를 받을 수 있다.
-- 테이블 풀 스캔 같은 성능에 영향을 미치는 쿼리는 nonstrict 모드에서만 동작한다. 기본 값은 nonstrict이다.
set hive.mapred.mode=nonstrict;
SELECT *
FROM tbl
ORDER BY id;
-- strict 모드 일때는 LIMIT 가 있어야만 처리 가능
set hive.mapred.mode=strict;
SELECT *
FROM tbl
ORDER BY id
LIMIT 100;
order by 와 비슷해 보일 수 있으나, order by의 경우에는 전체 결과를 하나의 리듀서가 정렬을 하게 되는 반면, sort by의 경우에는 각 리듀서에서 정렬을 하게 된다.
리듀서 별로 입력된 데이터를 정렬하여 출력한다. 리듀서 개수 만큼 생성되는 파일의 결과가 정렬되어 출력된다.
그로인해, 리듀서 갯수가 여러개 이기 때문에 성능에 이점을 볼 수 있다. 하지만, 각 리듀서에서만 정렬이 이루어지기 때문에 정확히 정렬된 결과물은 보장하지 않는다.
아래는 리듀서 2개를 이용하여 sort by 를 사용한 결과이다.
set mapred.reduce.tasks=2;
SELECT *
FROM tbl
SORT BY id;
단, 아래와 같이 리듀서를 1개만 사용한다면 ORDER BY와 결과가 동일하게 나온다.
즉, 리듀서 수를 여러개 사용한다면 order by보다 속도가 빠르지만, 최종 데이터가
모두 정렬되지 않아 정렬 용도로 사용은 불가능하다.
SET mapred.reduce.tasks=1
위 그림 처럼 column의 값을 기준으로 distribute by 를 리듀서 별로 같은 값이 들어가게 되며,
리듀서로 전달 할 때 정렬하여 전달하지는 않는다.
SQL의 GROUP BY와 비슷하게 접근하면 이해가 쉽다.
아래는 Role을 기준으로 distribute by를 사용한 예시이다.
select *
from tbl
distribute by Role
보통은 아래처럼 sort by와 함께 사용하거나 cluster by를 사용한다.
SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC
sort by 와 DISTRIBUTE by를 동시에 수행한다.
sort by 절 전에 DISTRIBUTE by 절을 사용할 것을 요구하므로 주의해야 한다.
같은 값을 가지는 row는 같은 리듀서에 전달되고, 리듀서 처리 결과를 정렬하여 출력한다.
Reference
https://m.blog.naver.com/jevida/222050932485
https://wikidocs.net/23560
https://velog.io/@crescent702/Hive-Sort-by-Distribute-by-Cluster-by-%ED%99%9C%EC%9A%A9%EB%8F%84-b1jw1gmzcc