내 머릿속 데이터베이스

[HIVE] UNION, SubQuery, With 테이블 합치기 팁. 본문

Programming/Bigdata / DataMining

[HIVE] UNION, SubQuery, With 테이블 합치기 팁.

파도소리 2017. 1. 9. 11:22

다수의 테이블을 합쳐서 통계를 산출 시에 UNION을 많이 사용하게 된다.


UNION과 UNION ALL의 차이는 다들 알고 있으리라 언급하자면 중복 데이터를 제거하는 과정이 UNION에 포함되어있다.


테이블을 합칠 때 UNION으로 합치게 되면 각 테이블마다 정렬이 들어가는 것을 실행계획을 통계 알 수 있다.

(그래서 느리다.)


UNION ALL 을 사용하게 되면 중복 상관없이 그냥 합쳐주기만 해서 빠르다.

다수의 테이블인 경우엔 각 테이블마다 중복데이터를 제거해가면서 합치는 것보다 일단 다 합쳐놓고 중복데이터를 제거하는게 빠르다.


실제로 UNION을 이용한 쿼리에선 HIVE의 CBO(Cost-based Optimizer)가 동작하지 않는다.




UNION ALL을 이용하여 테이블을 합치려다가 HIVE는 CTE(Common Table Expression) 을 지원한다는 사실을 알았다. 

WITH문으로 더 잘 알려진 이 구문은 오라클 사용자라면 알고 있을 것이다. 


단 MySQL은 지원하지 않으며, MariaDB는 10.2.1 버전부터 지원하고 있다.



UNION ALL을 이용하여 테이블을 합치는 방법은 다음 두가지가 있겠다.

1. 서브쿼리를 이용

2. with


위 두가지 방법으로 쿼리를 짜보고 실행계획을 보았으나 실행계획까지도 똑같다. 

with구문이 더 가독성이 좋다는데... 난 글쎄.. 그냥 쓰고 싶은거 써도 상관없다.


다음 두 쿼리는 동일하다.


SET TDATE='01'

SELECT COUNT(DISTINCT(usr_key)) FROM (

  SELECT mdate, usr_key FROM table1 WHERE mdate>=${hiveconf:TDATE}

  UNION ALL

  SELECT mdate, usr_key FROM table2 WHERE mdate>=${hiveconf:TDATE}

  UNION ALL

  SELECT mdate, usr_key FROM table3 WHERE mdate>=${hiveconf:TDATE}

  UNION ALL

  SELECT mdate, usr_key FROM table4 WHERE mdate>=${hiveconf:TDATE}

) t1


SET TDATE='01'

WITH t1 AS (SELECT usr_key FROM s1

  UNION ALL SELECT usr_key FROM s2

  UNION ALL SELECT usr_key FROM s3

  UNION ALL SELECT usr_key FROM s4

  ),

      s1 as (SELECT mdate, usr_key FROM table1 WHERE mdate>=${hiveconf:TDATE}),

      s2 as (SELECT mdate, usr_key FROM table2 WHERE mdate>=${hiveconf:TDATE}),

      s3 as (SELECT mdate, usr_key FROM table3 WHERE mdate>=${hiveconf:TDATE}),

      s4 as (SELECT mdate, usr_key FROM table4 WHERE mdate>=${hiveconf:TDATE})

SELECT COUNT(DISTINCT(usr_key)) FROM t1;


stackoverflow를 뒤져봐도 subquery와 with은 동일같거나 다름없다고 한다.

차이가 있다면 가독성의 차이와 with문이 recursive한 점인데.. recursive하게 활용하는 with문에 대해서 더 언급하고 싶었으나 길어지니 나중에.. 

Comments