https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy



하이브에서 사용되는 정렬 키워드를 소개한다.


* ORDER BY (ASC|DESC): RDMBS의 ORDER BY 문과 비슷하다. ORDER BY 문을 실행 시, 하나의 리듀서만 사용해 전역 정렬을 수행하면, 리턴 시간이 더 소요된다. ORDER BY 뒤에 LIMIT 사용하는 것을 강력 추천한다. 그래서, hive.mapred.mode = strict (hive.mapred.mode= nonstrict은 기본값이다.)로 설정하고 LIMIT을 명세하지 않으면, 에러가 발생한다. 



jdbc:hive2://> SELECT name FROM employee ORDER BY NAME DESC;

+----------+

|   name   |

+----------+

| Will     |

| Shelley  |

| Michael  |

| Lucy     |

+----------+



* SORT BY (ASC|DESC): 어떤 레코드의 컬럼으로 정렬할지 가리킨다. 데이터를 리듀서에 보내기 전에 정렬을 완료한다는 것을 의미한다. mapred.reduce.tasks=1을 설정하지 않는다면, SORT BY 문은 전역으로 정렬을 수행하지 않고, 각 리듀서에서 내부적으로 정렬된 데이터인지 확인한다. 이 경우에 ORDER BY 결과와 동일하다. 


--2 개의 리듀서를 사용하면 리듀서마다 정렬(sorting)하기 때문에 정렬 결과가 다르다.

jdbc:hive2://> SET mapred.reduce.tasks = 2;

No rows affected (0.001 seconds)


jdbc:hive2://> SELECT name FROM employee SORT BY NAME DESC;

+----------+

|   name   |

+----------+

| Shelley  |

| Michael  |

| Lucy     |

| Will     |

+----------+

4 rows selected (54.386 seconds)


--리듀서 한 개만 사용하면 order by 와 동일한 효과를 제공한다.

jdbc:hive2://> SET mapred.reduce.tasks = 1;

No rows affected (0.002 seconds)


jdbc:hive2://> SELECT name FROM employee SORT BY NAME DESC;

+----------+

|   name   |

+----------+

| Will     |

| Shelley  |

| Michael  |

| Lucy     |

+----------+

4 rows selected (46.03 seconds)



* DISTRIBUTE BY:  컬럼값이 일치하는 로우는 동일한 리듀서로 파티션 된다. 하나의 리듀서만 사용하면, 리듀스는 정렬된 입력을 보장하지 않는다. 매퍼 결과를 분배하기 위해 어느 리듀서로 결정할지 여부의 관점에서 보면, DISTRIBUTE BY는 RDBMS의 GROUP BY와 비슷하다. SORT BY를 사용할 때, SORT BY 앞에 DISTRIBUTE BY를 명세해야 한다. 그리고, 분배하기 위해 사용된 컬럼은 SELECT 뒤에 컬럼 이름이 나타나야 한다. 



- SQL의 GROUP BY와 같은 형태이기 때문에 select 뒤에 컬럼 이름이 나와야 한다.

jdbc:hive2://> SELECT name 

. . . . . . .> FROM employee_hr DISTRIBUTE BY employee_id; 

Error: Error while compiling statement: FAILED: SemanticException [Error 10004]: Line 1:44 Invalid table alias or column reference 'employee_id': (possible column names are: name) (state=42000,code=10004)


jdbc:hive2://> SELECT name, employee_id 

. . . . . . .> FROM employee_hr DISTRIBUTE BY employee_id; 

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Steven   | 102          |

| Will     | 101          |

| Michael  | 100          |

+----------+--------------+

4 rows selected (38.92 seconds)


--SORT BY로 사용하기 

jdbc:hive2://> SELECT name, employee_id  

. . . . . . .> FROM employee_hr 

. . . . . . .> DISTRIBUTE BY employee_id SORT BY name; 

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Michael  | 100          |

| Steven   | 102          |

| Will     | 101          |

+----------+--------------+

4 rows selected (38.01 seconds)



* CLUSTER BY: 동일한 그룹의 컬럼에 대해 DISTRIBUTE BY와 SORT BY 명령을 동시에 수행하는 명령어다. 그리고 내부적으로 각 리듀서에서 정렬된다. CLUSTER BY 문은 아직 ASC 또는 DESC를 지원하지 않는다. 전역으로 정렬되는 ORDER BY와 비교해, CLUSTER BY 명령은 각 분배된 그룹에서 정렬이 이루어진다. 전역 정렬을 실행할 때 사용할 수 있는 모든 리듀서를 작동시키려면, CLUSTER BY를 먼저 사용하고 뒤에 ORDER BY를 사용한다. 



jdbc:hive2://> SELECT name, employee_id 

. . . . . . .> FROM employee_hr CLUSTER BY name;  

+----------+--------------+

|   name   | employee_id  |

+----------+--------------+

| Lucy     | 103          |

| Michael  | 100          |

| Steven   | 102          |

| Will     | 101          |

+----------+--------------+

4 rows selected (39.791 seconds)



Posted by 김용환 '김용환'

댓글을 달아 주세요