OR 조건 vs AND 조건: 성능과 변환 기법의 실체
SQL 성능 최적화에서 WHERE 조건절은 쿼리 효율에 막대한 영향을 미친다. 특히 OR 조건과 AND, NOT 조건의 조합은 작은 차이처럼 보여도 결과적으로는 수배의 성능 차이를 야기할 수 있다.
1. OR 조건은 왜 느린가?
OR 조건은 RDBMS가 각 조건을 개별적으로 평가하고, 그 결과를 합집합(UNION) 방식으로 결합하기 때문에 비용이 커지는 경향이 있다.
예를 들어,
SQL
SELECT * FROM my_table
WHERE column = '1' OR column = '2';
위 쿼리는 내부적으로 두 조건 각각에 대해 인덱스를 타거나, 전체 스캔 후 필터링을 수행하게 된다. 특히 column에 인덱스가 있더라도, 두 조건을 인덱스로 효율적으로 병합하지 못하는 경우가 생긴다.
병렬 처리의 단점
OR 조건이 여러 개 걸릴 경우, 쿼리 플래너는 종종 전체 테이블 스캔(full scan) 을 선택한다. 이는 AND 조건과 비교해 더 많은 블록 I/O를 야기할 수 있다.
2. De Morgan 법칙을 활용한 OR → AND/NOT 변환
모든 OR 조건은 수학적 논리의 드모르간 법칙(De Morgan's Law) 을 이용해 AND와 NOT으로 변환이 가능하다.
예시 변환
SQL
column = '1' OR column = '2'
-- 는 다음과 동치
NOT (column != '1' AND column != '2')
또는 분포 기반 최적화로,
SQL
column = '1' OR column = '2'
-- 를
column NOT IN ('3', '4') -- 단, 값의 범위가 명확할 때만
으로 바꾸는 방법도 있다. 이 방식은 조건이 부정(NOT)으로 바뀌는 만큼, 인덱스를 활용하는 데 제약이 생길 수 있으므로 상황에 따라 신중하게 적용해야 한다.
3. 어떤 경우 OR가 더 빠를 수도 있다
조건을 NOT으로 바꾸었지만, 결과적으로 더 많은 데이터를 대상으로 필터링해야 하는 경우 성능은 오히려 저하된다. 예를 들어 다음의 경우를 보자.
SQL
-- 전체 데이터 중 95%가 '3' 또는 '4'
-- 5%만이 '1' 또는 '2'
-- 변환 전
column = '1' OR column = '2' -- 결과는 5% 대상
-- 변환 후
column NOT IN ('3', '4') -- 결과는 5% 대상이지만, 95%를 먼저 필터링해야 함
위와 같이 부정 조건으로 바꾼 필터가 훨씬 더 많은 데이터를 통과시키게 되는 경우, OR 조건이 오히려 빠르게 작동한다. 이때는 실제 데이터 분포 통계(histogram) 와 실행 계획(EXPLAIN PLAN) 을 반드시 확인해야 한다.
4. 인덱스와 결합 전략
대부분의 RDBMS는 단일 인덱스로는 OR 조건의 모든 조합을 최적화하지 못한다. 반면, UNION ALL로 분해하면 각 조건별 인덱스를 잘 활용할 수 있다.
OR 분해 예시:
SQL
-- 기존
SELECT * FROM my_table
WHERE column = '1' OR column = '2';
-- 분해
SELECT * FROM my_table WHERE column = '1'
UNION ALL
SELECT * FROM my_table WHERE column = '2';
이 방식은 각각의 쿼리가 개별적으로 인덱스를 탈 수 있게 하고, 병합도 간단해져 성능이 개선되는 경우가 많다.
5. 정리
조건 방식 | 장점 | 단점 |
---|---|---|
OR 조건 | 단순한 로직, 빠른 개발 | 인덱스 비효율, Full Scan 유도 가능성 |
AND + NOT 조건 | 인덱스 활용 기대 가능 (경우에 따라) | 부정 조건일 경우 인덱스 효율 저하 |
UNION ALL | 조건별 인덱스 활용, 병렬 가능성 높음 | 쿼리 길어짐, 로직 복잡도 증가 |
결론
- 단순한 OR 조건은 편하긴 하지만, 데이터 분포가 희박하거나 인덱스 효율이 떨어지는 경우 성능 병목이 발생할 수 있다.
- NOT, AND로 변환할 때는 분포 통계와 인덱스 구조를 고려한 설계가 필요하다.
- 최적의 전략은 실행 계획과 실제 통계를 기반으로 검증하면서 결정해야 한다.