Using union은 OR 조건에서 여러 인덱스 결과를 그냥 합치고, Using sort_union은 합친 후 정렬해서 중복 제거까지 수행하는 최적화 전략입니다.
WHERE 절에 OR 조건이 있을 때, MySQL은 각 조건에 대해 별도의 인덱스를 사용해 결과를 가져온 후 이를 합칩니다. 이때 두 가지 전략이 있습니다:
두 전략 모두 index_merge 최적화의 일부이며, OR 조건에서 여러 인덱스를 동시에 활용해 성능을 높이는 방법입니다.
1. Index Merge 최적화
MySQL은 WHERE 절에 여러 조건이 OR로 연결되어 있고, 각 조건이 서로 다른 인덱스를 사용할 수 있을 때 Index Merge 최적화를 적용합니다. 각 인덱스를 개별적으로 스캔한 후, 결과를 합치는(UNION) 방식으로 동작합니다.
2. OR 조건과 인덱스
일반적으로 OR 조건은 인덱스를 타기 어렵습니다. 예를 들어 WHERE col1 = 10 OR col2 = 20 같은 쿼리는 하나의 인덱스만으로는 최적화하기 어렵습니다. Index Merge는 이런 경우 col1 인덱스와 col2 인덱스를 각각 사용해 결과를 합치는 방식으로 성능을 개선합니다.
3. Primary Key와 중복 제거
테이블에서 같은 행이 여러 OR 조건에 동시에 만족할 수 있습니다. 예를 들어 WHERE age = 30 OR city = 'Seoul'에서 age도 30이고 city도 'Seoul'인 행은 두 인덱스 스캔 결과 모두에 포함됩니다. 이런 중복을 제거하기 위해 PK 기준 정렬 및 중복 제거가 필요할 수 있습니다.
언제 Using union을 사용하나?
각 인덱스 스캔 결과가 PK를 포함하고 있고, MySQL이 PK를 기준으로 자동으로 중복을 제거할 수 있을 때 사용됩니다. 예를 들어:
SELECT * FROM users
WHERE user_id IN (1,2,3) OR email = 'test@example.com';
이 쿼리는 user_id 인덱스와 email 인덱스를 각각 사용해 결과를 가져온 후, PK(user_id)가 자연스럽게 중복을 걸러주므로 Using union이 표시됩니다.
언제 Using sort_union을 사용하나?
인덱스 스캔 결과가 PK 순서대로 정렬되어 있지 않거나, 중복 제거를 위해 명시적인 정렬이 필요한 경우 사용됩니다. 특히 범위 조건(range)이 OR로 연결될 때 자주 발생합니다:
SELECT * FROM orders
WHERE (order_date BETWEEN '2026-01-01' AND '2026-01-31')
OR (order_date BETWEEN '2026-03-01' AND '2026-03-31');
각 범위 스캔 결과는 order_date 순으로 정렬되어 있지만 PK 순서는 아닙니다. 두 결과를 합칠 때 중복된 order_id가 있을 수 있으므로, PK로 정렬 후 중복 제거를 수행하며 Using sort_union이 표시됩니다.
성능 차이
실무 팁
가능하면 OR 조건보다는 IN 절이나 UNION ALL을 사용하는 것이 더 예측 가능한 성능을 제공합니다. Index Merge는 편리하지만, 복잡한 OR 조건에서는 실행 계획이 불안정할 수 있습니다.
왼쪽의 Using union은 각 인덱스 결과를 바로 합치고, 오른쪽의 Using sort_union은 PK로 정렬 후 중복을 제거하는 추가 단계를 거칩니다.
| 구분 | Using union | Using sort_union |
|---|---|---|
| 정렬 여부 | 정렬 없음 | PK로 정렬 수행 |
| 중복 제거 | 자동 (PK 기반) | 명시적 제거 (Unique) |
| 성능 | 빠름 | 정렬 비용 추가 |
| 사용 시기 | PK 포함 결과, 단순 OR | 범위 조건 OR, 복잡한 조건 |
| EXPLAIN 예시 | Using union(idx1,idx2) |
Using sort_union(idx1,idx2) |
| 결과 순서 | 보장 안됨 | PK 순서로 정렬됨 |