LanguageManual - Group By

LanguageManual - Group By

Hive에서 GROUP BY를 사용하는 방법을 정리한 문서예요. 기본 구문부터 위치 기반 컬럼 지정, 멀티 그룹 인서트, 맵사이드 집계, GROUPPING SETS/CUBE/ROLLUP 같은 고급 기능까지 다룹니다.

출처: 문서

본문

Group By 구문 (Group By Syntax)

groupByClause: GROUP BY groupByExpression (, groupByExpression)*

groupByExpression: expression

groupByQuery: SELECT expression (, expression)* FROM src groupByClause?

groupByExpression에서 컬럼은 위치 번호가 아니라 이름으로 지정됩니다. 단, Hive 0.11.0 이상에서는 다음과 같이 구성하면 위치로도 지정할 수 있습니다:

  • Hive 0.11.0 ~ 2.1.x: hive.groupby.orderby.position.alias를 true로 설정(기본값 false).
  • Hive 2.2.0 이상: hive.groupby.position.alias를 true로 설정(기본값 false).

간단한 예제 (Simple Examples)

테이블의 행 수를 세려면:

  SELECT COUNT(*) FROM table2;

HIVE-287이 포함되지 않은 Hive 버전에서는 COUNT(*) 대신 COUNT(1)을 사용해야 합니다.

성별별 고유 사용자 수를 세려면 다음 쿼리를 작성할 수 있습니다:

  INSERT OVERWRITE TABLE pv_gender_sum
  SELECT pv_users.gender, count (DISTINCT pv_users.userid)
  FROM pv_users
  GROUP BY pv_users.gender;

여러 집계를 동시에 할 수 있지만, 서로 다른 DISTINCT 컬럼을 가진 두 집계는 동시에 할 수 없습니다. 예를 들어 count(DISTINCT)와 sum(DISTINCT)가 같은 컬럼을 지정하므로 다음은 가능합니다:

  INSERT OVERWRITE TABLE pv_gender_agg
  SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(*), sum(DISTINCT pv_users.userid)
  FROM pv_users
  GROUP BY pv_users.gender;

HIVE-287이 포함되지 않은 Hive 버전에서는 COUNT(*) 대신 COUNT(1)을 사용해야 합니다.

그러나 다음 쿼리는 허용되지 않습니다. 같은 쿼리에서 여러 DISTINCT 표현식을 허용하지 않습니다.

  INSERT OVERWRITE TABLE pv_gender_agg
  SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(DISTINCT pv_users.ip)
  FROM pv_users
  GROUP BY pv_users.gender;

Select 문과 group by 절 (Select statement and group by clause)

group by 절을 사용할 때 select 문은 group by 절에 포함된 컬럼만 포함할 수 있습니다. 물론 select 문에는 원하는 만큼 많은 집계 함수(예: count)를 넣을 수 있습니다. 간단한 예를 들어봅시다.

CREATE TABLE t1(a INTEGER, b INTGER);

위 테이블에 대한 group by 쿼리는 다음과 같을 수 있습니다:

SELECT
   a,
   sum(b)
FROM
   t1
GROUP BY
   a;

select 절에 a(group by 키)와 집계 함수(sum(b))가 포함되어 있으므로 위 쿼리는 동작합니다.

그러나 아래 쿼리는 동작하지 않습니다:

SELECT
   a,
   b
FROM
   t1
GROUP BY
   a;

이는 select 절에 group by 절에 포함되지 않은(그리고 집계 함수도 아닌) 추가 컬럼(b)이 있기 때문입니다. 테이블 t1이 다음과 같다고 가정해 봅시다:

a    b
------
100  1
100  2
100  3

그룹핑이 a에만 수행되므로, a=100 그룹에 대해 Hive가 표시해야 할 b 값은 무엇일까요? 첫 번째 값이어야 한다고 주장할 수도, 최소값이어야 한다고 주장할 수도 있지만, 여러 가능한 옵션이 있다는 데 모두 동의할 것입니다. Hive는 select 절에 group by 절에 포함되지 않은 컬럼을 두는 것을 유효하지 않은 SQL(HQL, 정확히는)로 만들어 이런 추측을 없앴습니다.

고급 기능 (Advanced Features)

멀티 그룹-By 인서트 (Multi-Group-By Inserts)

집계 또는 단순 select의 출력은 여러 테이블로, 심지어 hadoop dfs 파일(그 후 hdfs 유틸리티로 조작 가능)로도 보낼 수 있습니다. 예를 들어 성별 분석과 함께 연령별 고유 페이지뷰 분석이 필요하다면 다음 쿼리로 해결할 수 있습니다:

  FROM pv_users
  INSERT OVERWRITE TABLE pv_gender_sum
    SELECT pv_users.gender, count(DISTINCT pv_users.userid)
    GROUP BY pv_users.gender
  INSERT OVERWRITE DIRECTORY '/user/facebook/tmp/pv_age_sum'
    SELECT pv_users.age, count(DISTINCT pv_users.userid)
    GROUP BY pv_users.age;

Group By의 맵사이드 집계 (Map-side Aggregation for Group By)

hive.map.aggr은 집계 방식을 제어합니다. 기본값은 false입니다. true로 설정하면 Hive가 1차 집계를 map 태스크에서 직접 수행합니다. 보통 더 나은 효율을 제공하지만 성공적으로 실행하기 위해 더 많은 메모리가 필요할 수 있습니다.

  set hive.map.aggr=true;
  SELECT COUNT(*) FROM table2;

HIVE-287이 포함되지 않은 Hive 버전에서는 COUNT(*) 대신 COUNT(1)을 사용해야 합니다.

Grouping Sets, Cubes, Rollups, 그리고 GROUPING__ID 함수

Version

Grouping sets, CUBE·ROLLUP 연산자와 GROUPING__ID 함수는 Hive 0.10.0 릴리스에서 추가되었습니다.

이 집계 연산자에 대한 정보는 Enhanced Aggregation, Cube, Grouping and Rollup 문서를 참고하세요.

다음 JIRA도 참고하세요:

  • HIVE-2397 Support with rollup option for group by
  • HIVE-3433 Implement CUBE and ROLLUP operators in Hive
  • HIVE-3471 Implement grouping sets in Hive
  • HIVE-3613 Implement grouping_id function

Hive 0.11.0 릴리스 신규:

  • HIVE-3552 많은 수의 grouping set 키에 대해 cubes/rollups/grouping sets를 수행하는 성능 개선

더 알아보기 (Learn more)

GROUP BY는 그룹 키 컬럼과 집계 함수만 select에 올릴 수 있고, 여러 DISTINCT를 같은 쿼리에 쓸 수 없어요. 멀티 테이블/디렉터리 인서트, hive.map.aggr 맵사이드 집계, 그리고 CUBE/ROLLUP/GROUPING__ID 등 고급 집계는 참고 문서를 함께 보면 좋아요.