DBDBDEEP
Union vs. Union All 본문
Union 과 Union All 둘 다 두개 이상의 Select 결과를 합치는 SQL 연산자인데 중요한 차이가 있다.
UNION
- 옵티마이저는 상단과 하단 두 집합간 중복을 제거하기 위하여 소트 작업을 수행한다.
- 중복 제거 때문에 정렬/해시 수행하기에 느리다.
UNION ALL
- 중복을 확인하지 않고 단순히 결합하기 때문에 소트작업을 수행하지 않는다.
- 중복 제거를 하지 않기 때문에 속도가 빠르다.
따라서 될 수 있으면 Union All을 사용해야한다.
CASE 1. 다음 모델에, 다음과 같이 SQL 사용시 Union All 을 사용해도 될까?

SELECT 결제번호, 주문번호, 결제금액, 주문일자 ..
FROM 결제
WHERE 결제수단코드 ='M' AND 결제일자 = '20180316'
UNION
SELECT 결제번호, 주문번호, 결제금액, 주문일자..
FROM 결제
WHERE 결제수단코드 ='C' AND 결제일자 '20180316'
결제수단코드가 다르기 때문에 중복데이터가 들어가지 않는다.
그럼에도 불구하고 Union을 사용해서 Sort 연산을 발생시키고 있고 성능저하를 유발하고 있다.

'이런 경우는 Union All로 대체해서 SQL을 작성하도록 하자'
CASE 2. Union All 을 사용하면 안되는 케이스
SELECT 결제번호, 주문번호, 결제금액, 주문일자 ..
FROM 결제
WHERE 결제일자 = ' 20180316'
UNION
SELECT 결제번호, 주문번호, 결제금액, 주문일자..
FROM 결제
WHERE 주문일자 = '20180316'

결제일자와 주문일자 조건은 상호배타적인 조건이 아니고 중복 조건이 발생할 수 있다.
Union 을 Union All 로 변경하면, 결제일자와 주문일자가 같은 결제 데이터가 중복해서 출력된다.
소트연산이 일어나지 않도록 Union All을 사용하고 싶으면서도
데이터 중복을 피하려면
SELECT 결제번호, 주문번호, 결제금액, 주문일자 ..
FROM 결제
WHERE 결제일자 = ' 20180316'
UNION ALL
SELECT 결제번호, 주문번호, 결제금액, 주문일자..
FROM 결제
WHERE 주문일자 = '20180316'
and 결제일자 <> '20183016'
을 사용하면 된다.
만약 결제일자가 NULL 허용 컬럼이면 조건을 아래와 같이 변경한다
and (결제일자 <> '20183016' or 결제일자 is null)
and LNNVL (결제일자 = '20183016')
이런 케이스는 흔하지 않지만 데이터 모델링 확인을 잘 해야하는 케이스인 것 같다.
'친절한 SQL 튜닝' 카테고리의 다른 글
| 6.3.2 파티션 (0) | 2026.05.18 |
|---|---|
| 5.3 인덱스를 이용한 Sort 연산 생략 (0) | 2026.05.18 |
| 스칼라 서브쿼리 캐싱효과 (장/단점) (0) | 2026.05.18 |
| 서브쿼리 언네스팅 (0) | 2026.05.18 |
| 4.4 서브쿼리 (0) | 2026.05.18 |