Hive ORDER BY, SORT BY, DISTRIBUTE BY, CLUSTER BY

 

·       Version : Hive

 

하이브 또는 RDBMS에서 ORDER BY 쿼리 결과 집합에 대해서 전체 정렬을 수행한다. 하이브에서 ORDER BY 모든 데이터가 하나의 리듀서로 처리되기 때문에 데이터 셋이 클수록 시간이 오래 걸린다. ORDER BY 오랜 시간을 수행될 있기 때문에 하이브는 hive.mapred.node strict 설정되었을 경우 ORDER BY절에 대해서 LIMIT 요구한다. 기본값은 nonstrict 이다.

 

 

하이브에서 ORDER BY 대신 SORT BY 사용하면 리듀서에서 지역 정렬하여 출력한다. ORDERSORT 사용할 경우 어떠한 컬럼이라도 지정할 수도 있고 ASC(기본값), DESC 사용하여 정렬할 수도 있다.  SORT BY 사용하는 경우 하나 이상의 리듀서로 처리될 경우 리듀서의 파일이 정렬되어 있더라도 전체적으로는 다른 리듀서의 출력된 정렬 결과가 겹치기 때문에 전체 정렬순서는 보장되지 않는다.

 

DISTRIBUTE BY 맵의 출력을 리듀서로 어떻게 나누어 보내는지를 제어한다. 하이브는 쿼리를 맵리듀스 잡으로 변환할때 내부적으로 기능을 사용하기도 한다. 기본적으로 맵리듀스는 맵퍼가 출력하는 키에 대해서 해시값을 계산하고 해시값을 이용하여 - 쌍을 가용한 리듀서로 균등하게 분산하려고 노력한다. 이때 SORT BY 사용할때 하나의 리듀서 출력이 다른 리듀서의 출력과 정렬 결과가 겹칠수 있다. 하지만 리듀서 출력 내에서는 정렬되어 있다. 하둡이 같은 데이터 레코드는 같은 리듀서로 보내는 것을 보장하기 위해서 DISTRIBUTE BY 사용할 있다. 그리고 리듀서 별로 데이터를 정렬하기 위해 SORT BY 사용한다.

 

 

SORT BY 리듀서 안에서 데이터 정렬을 제어하는 반면 DISTRIBUTE BY 리듀서가 처리할 로우를 어떻게 받는지 제어한다는 점에서는 GROUP BY처럼 동작한다. 하이브는 SORT BY 전에 DISTRIBUTE BY 절을 사용할 것을 요구하므로 주의해야한다.

 

CLUSTER BY 같은 쿼리를 표현하는 간단한 방법이다.

 

 

2020-08-03 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, 하이브 정렬,  ORDER BY, SORT BY, DISTRIBUTE BY, CLUSTER BY

Hive Map-Side-Join,  Bucket-Map-Join, Sort-Merge-Join

 

·       Version : Hive

 

Hive에서 조인 명령을 실행할때, 크기가 작은 테이블은 메모리에 캐시하고 크기가 테이블은 맵퍼로 흘려 보낼 있다. 하이브는 메모리에 캐시한 작은 테이블로 부터 일치하는 모든 것을 찾아 있기 때문에 맵에서 모든 조인을 있다. 이렇게 하면 일반 조인 시나리오에서 필요한 리듀스 단계를 제거할 있다.

 

데이터가 작을 수록 사이드 조인은 일반 조인보다 효율이 좋다. 리듀스 단계를 제거할 뿐만 아니라 단계 역시 줄어들기 때문이다. 사이드 조인을 활성화 하기 위해서는 hive.auto.convert.join 속성을 true 설정해야한다. 기본값은 false 이다. 사이드 조인을 사용하기 위한 테이블 크기 임계치는 hive.mapjoin.smalltable.filesize 속성값을 설정한다. 단위는 바이트 이다.

hive> set hive.auto.convert.join=true;

hive> set hive.auto.convert.join.noconditionaltask=true;

hive> set hive.auto.convert.join.noconditionaltask.size=20971520

hive> set hive.auto.convert.join.use.nonstaged=true;

hive> set hive.mapjoin.smalltable.filesize = 30000000;

 

 

사이드 조인은 특정 조건에서는 테이블에서도 사용할 있다. 이러한 조건은 ON 절에서 사용할 키에 대해서 버킷팅이 되어 있어야 하고, 테이블의 버킷 수가 다른 테이블 버킷 수의 배수이어야 한다. 이러한 조건이 충족되면 하이브는 다른 테이블의 버킷을 매칭하기 위해 모든 테이블의 내용을 가져올 필요 없이 테이블 간의 버킷에 대해 사이드 조인을 있다.   옵션을 사용하기 위해서는 hive.optimize.bucketmapjoin 속성값을 ture 설정해야 한다.

hive> set hive.optimize.bucketmapjoin=true;

 

만약 버킷팅되어 있는 테이블이 같은 수의 버킷을 가지고 있고, 데이터는 조인/버킷 키로 정렬되어 있다면 하이브는 정렬-병합 조인(Sort Merge Join) 수행하여 빠르게 조인할 있다.

 

옵션을 사용하기 위해서는 아래 설정을 활성화 해야 한다.

hive> set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;

hive> set hive.optimize.bucketmapjoin=true;

hive> set hive.optimize.bucketmapjoin.sortedmerge=true;

 

 

 

참고자료

·       Map Join in Hive | Map Side Join : https://data-flair.training/blogs/map-join-in-hive/

·       Bucket Map Join in Hive – Tips & Working : https://data-flair.training/blogs/bucket-map-join/

·       Sort Merge Bucket Join in Hive – SMB Join : https://data-flair.training/blogs/hive-sort-merge-bucket-join/

 

 

 

2020-07-28 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, Hive Map Join, Hive Bucket Join, Hive Sort Merge Join, 조인 최적화, 하이브 튜닝

Hive Left Semi Join (세미 조인) Cartesian Product Join (카테시안 프로덕트 조인)

 

·       Version : Hive

 

Hive에서 Left Semi Join (왼쪽 세미 조인) 오른쪽 테이블에서 ON 조건을 만족하는 레코드를 찾을 경우 왼쪽 테이블의 레코드를 반환한다.

 

일반적인 RDBMS SQL 조건을 만족하기 위해 IN 또는 EXISTS 구문을 지원하지만, 하이브에서는 동작하지 않는다. 하이브는 기본적으로 Right Semi Join (오른쪽 세미 조인) 지원하지 않으며 SELECT WHERE절에서 오른쪽 테이블의 컬럼을 참조 없음에 주의해야 한다.  아래 스크립트는 하이브에서 사용할 있는 Left  Semi Join 예시이다.

select

       a.col_1, a.col_2

from tbl_a as a

       left semi join tbl_b as b on a.col_1 = b.col_1 and a.col_2 = b.col_2

 

하이브에서 세미 조인이 일반 내부 조인보다 효율적인 이유는 왼쪽 테이의 레코드에 대해서 오른쪽 테이블에서 일치하는 레코드를 찾으면 이상 일치하는 레코드를 찾지 않고 바로 데이터를 반환하고 멈추기 때문이다.

 

카테시안 프로덕트 조인(Cartesian Product Join) 조인의 왼쪽 테이블에 있는 튜플(tuple) 오른쪽에 있는 튜플이 모든 쌍을 맺는다. 다른 조인 유형과 달리 하이브에서는 카테시안 프로덕트를 병렬로 실행하지 않는다. 또한 맵리듀스에서 최적화되어 있지도 않다. 아래 스크립트는 하이브에서 전체 카테시안 프로덕트(Full Cartesian Product) 실행한다.

select

       a.*, b.*

from tbl_a as a

       join tbl_b as b

where a.col_1 = b.col_1

 

일반적인 RDBMS에서는 위와 같은 쿼리에 대해서 내부 조인에 최적화되어 있으나, 하이브에서 이런 종류의 쿼리는 WHERE 절을 적용하기 전에 전체 카테시안 프로덕트를 실행한다. 그래서 쿼리가 아주 오래 걸릴 있다. 사용자 부주의로 카테시안 프로덕트를 방지하기 위해 hive.mapred.mode 속성이 strict 되어 있으면 카테시안 프로덕트의 실행을 방지 있다.

 

 

2020-07-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, HIVE LEFT SEMI JOIN, 하이브 최적화, 하이브 튜닝, Hive Tuning, Hive Query Hint, CartesianProductJoin, 카테시안조인

Hive JOIN 조인 최적화

 

·       Version : Hive

 

Hive RDBMS 같은 JOIN(조인) 구문을 제공하며 기능도 거의 유사하지만 동등조인(EQUI-JOIN) 제공한다.

 

내부조인(INNER JOIN) 경우 조인하는 모든 테이블에서 일치하는 레코드만 반환한다. ON 절은 테이블에서 조인할 레코드의 조건을명시한다.

select

       a.col_1, b.col_2

from tbl_a

       inner join tbl_b on a.col_1 = b.col_1

 

RDBMS 표준 SQL 경우 조인 키에 대해서 비동등 조인(NON-EQUI-JOIN) 허용하지만 하이브에서는 제공하지 않는다. 또한 하이브에서는 ON절에서 OR 조건의 사용을 허용하지 않는다. 만약 ON 절에 OR 사용하려고 한다면 아래 스크립트와 같이 UNION ALL으로 쿼리를 풀어서 사용할 있다.

select

       *

from test1 as t1

       join test2 as t2 on (t1.col1 = t2.col1 and t1.col1 = 1) or (t1.col1 = t2.col2 and t1.col1 = 2);

 

/* OR 대신 UNION ALL 사용 */

select

       *

from test1 as t1

       join test2 as t2 on (t1.col1 = t2.col1 and t1.col1 = 1)

 

union all

 

select

       *

from test1 as t1

       join test2 as t2  on (t1.col1 = t2.col2 and t1.col1 = 2);

 

 

대부분의 하이브는 조인할 각각의 쌍에 대해서 별도의 맵리듀스 잡을 사용한다. 또한 하이브는 왼쪽에서 오른쪽으로 쿼리를 처리하며 조인 순서 또한 왼쪽에서 오른쪽(from 순서)으로 처리한다. 3 이상의 테이블을 조인할 , 모든 ON 절에서 같은 조인키를 사용한다면 하나의 맵리듀스 잡을 사용한다.

 

하이브에서 조인을 처리할때, 마지막 테이블을 가장 크다고 가정한다. 다른 테이블을 버퍼링하려고 시도하고, 레코드에 대해서 조인을 수행하면서 마지막 테이블을 흘려보낸다. 그러므로 조인쿼리를 구성할때, 가장 테이블을 가장 마지막에 위치하도록 해야한다. 가장 테이블을 쿼리의 마지막에 위치하지 못하였더라도 힌트를 사용하면 마지막에 처리할 있다. 아래 스크립트는 힌트를 사용하여 from 테이블을 마지막에 처리할 있도록 한다.

SELECT

       /*+ STREAMTABLE(s) */ s.*, b.*

from tbl_s   

       inner join tbl_b ON s.col_1 = b.col_1

where s.col_1 = ?

 

 

데이터 조회시 검색 최적화를 위해 파티션 필터를 사용하는데 OUTER JOIN (외부조인) 경우 파티션 필터를 무시한다. 하지만 내부 조인의 ON절에 파티션 필터를 사용하면 동작한다. 따라서 모든 조인에서 파티션 필터를 사용하기 위해 중첩 SELECT 사용하여 해결할 있다.

select

       a.col_1, b.col_1

from (select * from tbl_a where partition_filter = ? and col_1 = ?) as a

       left outer join (select * from tbl_b where partition_filter = ? and col_1 = ?) as b on a.col_1 = b.col_1

 

중첩 SELECT 문은 데이터 조인 전에 파티션 필더를 적용하는데 필요한 푸시다운(push down) 수행한다. 하이브는 조인을 수행한 후에 WHERE 절을 평가한다. 따라서 WHERE 절은 NULL 되지 않는 컬럼값에 대해서만 필터를 적용할 있도록 해야한다.

 

 

2020-07-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, JOIN, INNER JOIN, 하이브 최적화, 하이브 튜닝, Hive Tuning, Hive Query Hint

+ Recent posts