- Today
- Total
내 머릿속 데이터베이스
[HIVE] UNION, SubQuery, With 테이블 합치기 팁. 본문
다수의 테이블을 합쳐서 통계를 산출 시에 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문에 대해서 더 언급하고 싶었으나 길어지니 나중에..