ORDER BY, SORT BY, CLUSTER BY, DISTRIBUTE BY
ORDER BY, SORT BY, CLUSTER BY, DISTRIBUTE BY
SELECT 절의 ORDER BY, SORT BY, CLUSTER BY, DISTRIBUTE BY 구문을 설명하는 문서예요. 각각이 데이터를 어떻게 정렬·분배하는지가 다르므로 정확히 구분해서 이해해야 합니다.
출처: 문서
본문
Order By 구문
Hive QL의 ORDER BY 구문은 SQL 언어의 ORDER BY 구문과 유사합니다.
colOrder: ( ASC | DESC )
colNullOrder: (NULLS FIRST | NULLS LAST) -- (Note: Available in Hive 2.1.0 and later)
orderBy: ORDER BY colName colOrder? colNullOrder? (',' colName colOrder? colNullOrder?)*
query: SELECT expression (',' expression)* FROM src orderBy
order by 절에는 몇 가지 제한이 있어요.
- strict 모드(
hive.mapred.mode=strict)에서는order by절 뒤에limit절이 와야 합니다.hive.mapred.mode를 nonstrict로 설정하면limit절이 필요 없어요. - 이유: 전체 결과에 전체 순서를 부여하려면 최종 출력을 정렬할 reducer가 하나 있어야 해요. 출력 행 수가 너무 많으면 단일 reducer가 끝나는 데 매우 오래 걸릴 수 있습니다.
- 컬럼은 위치 번호가 아니라 이름으로 지정됩니다. 단, Hive 0.11.0 이후에서는 다음과 같이 설정하면 위치로도 지정할 수 있어요.
- Hive 0.11.0 ~ 2.1.x:
hive.groupby.orderby.position.alias를true로 설정 (기본값은false) - Hive 2.2.0 이상:
hive.orderby.position.alias가 기본적으로true
- Hive 0.11.0 ~ 2.1.x:
- 기본 정렬 순서는 오름차순(
ASC)입니다. - Hive 2.1.0 이상에서
order by절의 각 컬럼에 대한 null 정렬 순서 지정을 지원해요.ASC순서의 기본 null 정렬은NULLS FIRST,DESC순서의 기본 null 정렬은NULLS LAST입니다. - Hive 3.0.0 이상에서 서브쿼리와 뷰에서 limit 없는
order by는 최적화기가 제거해요. 비활성화하려면hive.remove.orderby.in.subquery를false로 설정하세요.
Sort By 구문
SORT BY 구문도 SQL의 ORDER BY 구문과 유사합니다.
colOrder: ( ASC | DESC )
sortBy: SORT BY colName colOrder? (',' colName colOrder?)*
query: SELECT expression (',' expression)* FROM src sortBy
Hive는 행을 reducer에 공급하기 전에 SORT BY의 컬럼으로 행을 정렬해요. 정렬 순서는 컬럼 타입에 따라 달라집니다. 숫자 타입이면 숫자 순서로, 문자열 타입이면 사전순(lexicographical)으로 정렬돼요.
Hive 3.0.0 이상에서 서브쿼리와 뷰에서 limit 없는 sort by는 최적화기가 제거해요. 비활성화하려면 hive.remove.orderby.in.subquery를 false로 설정하세요.
Sort By와 Order By의 차이
Hive는 reducer별로 데이터를 정렬하는 SORT BY를 지원해요. order by와 sort by의 차이는, 전자가 출력에 전체 순서(total order)를 보장하는 반면 후자는 reducer 내 행의 정렬만 보장한다는 점입니다. reducer가 둘 이상이면 sort by는 부분적으로 정렬된 최종 결과를 낼 수 있어요.
참고: 단일 컬럼의 SORT BY와 CLUSTER BY의 차이가 혼동될 수 있어요. 차이는 CLUSTER BY는 필드로 파티셔닝하고, 여러 reducer가 있을 때 SORT BY는 데이터(및 부하)를 reducer에 균등하게 분배하기 위해 랜덤으로 파티셔닝한다는 점입니다. 기본적으로 각 reducer의 데이터는 사용자가 지정한 순서대로 정렬됩니다.
SELECT key, value FROM src SORT BY key ASC, value DESC
이 쿼리는 2개의 reducer가 있고, 각각의 출력은 다음과 같습니다.
0 5
0 3
3 6
9 1
0 4
0 3
1 1
2 5
Sort By를 위한 타입 설정 (Setting Types for Sort By)
transform 이후 변수 타입은 일반적으로 문자열로 간주되는데, 이는 숫자 데이터가 사전순으로 정렬된다는 뜻이에요. 이를 해결하기 위해 SORT BY를 사용하기 전에 cast를 포함한 두 번째 SELECT 문을 사용할 수 있습니다.
FROM (FROM (FROM src
SELECT TRANSFORM(value)
USING 'mapper'
AS value, count) mapped
SELECT cast(value as double) AS value, cast(count as int) AS count
SORT BY value, count) sorted
SELECT TRANSFORM(value, count)
USING 'reducer'
AS whatever
Cluster By와 Distribute By 구문
CLUSTER BY와 DISTRIBUTE BY는 주로 Transform/Map-Reduce 스크립트와 함께 사용돼요. 하지만 후속 쿼리를 위해 쿼리 출력을 파티셔닝·정렬할 필요가 있을 때 SELECT 문에서도 유용할 수 있습니다.
CLUSTER BY는 DISTRIBUTE BY와 SORT BY 둘 다의 단축 형태(short-cut)예요. Hive는 DISTRIBUTE BY의 컬럼을 사용해 행을 reducer들 사이에 분배합니다. 같은 DISTRIBUTE BY 컬럼을 가진 모든 행은 같은 reducer로 갑니다. 하지만 DISTRIBUTE BY는 분배 키에 클러스터링이나 정렬 속성을 보장하지 않아요.
예를 들어 다음 5개 행을 2개 reducer로 DISTRIBUTE BY x한다고 해볼게요.
x1
x2
x4
x3
x1
Reducer 1은 다음을 받았습니다.
x1
x2
x1
Reducer 2는 다음을 받았습니다.
x4
x3
같은 키 x1의 모든 행은 같은 reducer(이 경우 reducer 1)로 분배되는 것이 보장되지만, 인접한 위치에 클러스터링된다는 보장은 없어요. 반면 CLUSTER BY x를 사용하면 두 reducer가 행을 x로 추가 정렬합니다.
Reducer 1:
x1
x1
x2
Reducer 2:
x3
x4
CLUSTER BY 대신 DISTRIBUTE BY와 SORT BY를 지정하면 파티션 컬럼과 정렬 컬럼을 다르게 할 수 있어요. 보통 파티션 컬럼이 정렬 컬럼의 접두어지만 반드시 그래야 하는 것은 아닙니다.
SELECT col1, col2 FROM t1 CLUSTER BY col1
SELECT col1, col2 FROM t1 DISTRIBUTE BY col1
SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC
FROM (
FROM pv_users
MAP ( pv_users.userid, pv_users.date )
USING 'map_script'
AS c1, c2, c3
DISTRIBUTE BY c2
SORT BY c2, c1) map_output
INSERT OVERWRITE TABLE pv_users_reduced
REDUCE ( map_output.c1, map_output.c2, map_output.c3 )
USING 'reduce_script'
AS date, count;
컬럼은 위치 번호가 아니라 이름으로 지정돼요. 단, HIVE-28572 이후에서는 다음과 같이 설정하면 위치로 지정할 수 있습니다.
set hive.orderby.position.alias =true;
set hive.cbo.enable =true;
위 조건 중 하나라도 충족되지 않으면 분배가 수행되지 않아요. 다음 예시에서는 3번째와 1번째 컬럼(birthdate, age)으로 분배합니다.
set hive.orderby.position.alias = true;
set hive.cbo.enable = true;
SELECT age, name, birthdate
FROM author DISTRIBUTE BY 3, 1;
더 알아보기 (Learn more)
ORDER BY는 전체 정렬(1개 reducer), SORT BY는 reducer 내 정렬, DISTRIBUTE BY는 키 기반 분배, CLUSTER BY는 분배+정렬이라는 점을 기억하세요. 대용량 결과의 전역 정렬이 필요하면 ORDER BY ... LIMIT로 단일 reducer 부하를 통제하는 것이 안전합니다.