UNION 과 JOIN 차이점
JOIN
여러 테이블에서 조건에 맞는 레코드를 찾아
컬럼
을 확장함.고객 테이블과 주문 테이블 조회
고객 이름 옆에 주문 내역이 추가로 붙어서 결과가 나옴
특징
인덱스 잘 활용하면, 데이터를 바로 가져올 수 있음
임시 테이블
이 필요가 없어진다.
UNION
여러 쿼리나 테이블의 결과를 모아서
레코드
를 확장특징
임시 테이블
을 사용해서 결과를 가공해야 한다.인덱스를 아무리 잘써도 해당 과정을 피할 수 없다
UNION 종류
UNION ALL
여러 결과 셋을
중복 여부 상관없이 그대로 합쳐서 반환
한다동작 방식
첫 번째 쿼리 결과를 가져온다
두 번째 쿼리 결과를 그 아래에 붙인다
끝 ㅋㅋ
장점
빠른 반환
쿼리 실행 중에도 일부 결과(첫 10건 등.. ) 을 클라이언트가 받을 수있다.
임시 테이블이 필요없다
UNION DISTINCT ( UNION )
여러 결과 셋에서
중복된 레코드를 제거
한 뒤에 반환한다.동작 방식
모든 쿼리 결과를 가져온다
임시 테이블
을 만들어서 결과에 저장한다.중복 제거한 뒤에 클라이언트에 반환한다.
특징
임시 테이블을 사용한다
중복 제거를 위해서 모든 데이터를 정렬하고 비교해야 한다.
느린 반환
모든 처리가 끝나야 결과를 보낸다.
왜 UNION DISTINCT 가 느린가?
동작 과정
임시 테이블 생성
쿼리 결과와 똑같은 구조의 임시 테이블을 만든다
모든 컬럼을 포함한
유니크 인덱스
를 생성
중복 체크 + 삽입
결과셋의 각 레코드를 하나씩 확인한다
SELECT
를 통해 임시 테이블에 동일한 레코드가 있는지 확인 한다.없으면
INSERT
로 추가있으면 무시한다.
결과 반환
모든 레코드 처리가 끝나는 경우 임시 테이블에서 데이터를 읽어서 클라이언트로 보낸다.
임시 테이블 삭제처리
작업이 끝나는 경우 임시테이블을 지운다.
중복 판단의 기준
PK 나 유니크 인덱스가 아니라, 모든 컬럼 값이 동일한지 비교한다.
왜 PK 를 사용하지 않느냐고 한다면
UNION 의 경우 서로 다른 테이블이나 가공된 결과셋를 다루기에
가져오는 데이터에 PK 가 없을 수 있음.
UNION DISTINCT성능 문제있음.
컬럼 수가 많을 수록 느려진다..
컬럼 5 vs 500개인 경우 중복 체크하는 경우, 비교해야 할 값이 100배가 늘어나게 된다.
임시 테이블의 유니크 인덱스도 커져서 메모리와 CPU 의 부담이 증가한다.
결론
UNION DISTINCT 는 꼭 필요한 경우가 아니라면 피하는 것이 좋다.
성능 테스트
mydb> select *
from employees_comp4k
union all
select *
from employees_comp8k
[2025-03-23 13:51:18] 6 s 690 ms (execution: 7 ms, fetching: 6 s 683 ms)에서 1부터 600,048개 행을 불러왔습니다
...
//
mydb> select *
from employees_comp4k
union
distinct
select *
from employees_comp8k
[2025-03-23 13:52:32] 4 s 281 ms (execution: 964 ms, fetching: 3 s 317 ms)에서 1부터 300,024개 행을 불러왔습니다
두 테이블이 완전 동일한 경우에는
union distinct 성능이 당연히 좋았다.
mydb> select *
from salaries
where 10000 <= salaries.emp_no
and salaries.emp_no <= 200000
union all
select *
from salaries
where 200000 < salaries.emp_no
and salaries.emp_no <= 300000
[2025-03-23 13:58:50] 18 s 393 ms (execution: 6 ms, fetching: 18 s 387 ms)에서 1부터 1,897,693개 행을 불러왔습니다
mydb> select *
from salaries
where 10000 <= salaries.emp_no
and salaries.emp_no <= 200000
union
distinct
select *
from salaries
where 200000 < salaries.emp_no
and salaries.emp_no <= 300000
[2025-03-23 13:59:12] 21 s 969 ms (execution: 3 s 594 ms, fetching: 18 s 375 ms)에서 1부터 1,897,693개 행을 불러왔습니다
중복이 없는 경우
UNION ALL 이 약 3.576초(16%) 더 빠르다.
실행 시간으로는
UNION ALL 6ms
UNION DISTINCT 3,594ms
으로서
UNION DISTINCT
가 실행 단계에서 훨씬 더 오래 걸린다.중복 제거(DISTINCT) 작업때문으로 보인다.
페칭 시간은
동일
UNION 쿼리 팁
불필요한 컬럼은 뺴고 들고와라!
UNION ALL 은 왠만하면 사용하고 차라리 어플리케이션 단에서 중복 제거하는 것도 좋은 방법이다.
UNION ALL 은 어플리케이션 서버에서 10개씩 끊어서 처리할 수 있다.
UNION 주의
UNION 의 경우
UNION 으로만 사용하는 경우
UNION DISTINCT 라고 인식하기에
꼭 UNION ALL 인 경우 다 써줘야한다!