Zettelkasten

OR 연산은 인덱스의 연속 스캔을 방해해 비효율을 유발한다.

·수정 2026.04.23·수정 1

요약

  • OR 연산은 인덱스의 연속 스캔(range scan)을 방해하여 비효율을 유발한다
  • 특히 서로 다른 컬럼 간의 OR 조건이 문제가 된다

본문

핵심 원리

B-Tree 인덱스는 정렬된 구조로, 연속된 범위를 스캔하도록 설계되어 있다. OR 연산은 "A 아니면 B"를 찾아야 하므로 이 연속 스캔의 이점을 살리기 어렵다.

문제가 되는 케이스: 서로 다른 컬럼 간 OR

SELECT * FROM users
WHERE name = 'kim' OR email = 'test@example.com'
  • 두 컬럼 모두 인덱스가 있어도 각각 스캔 후 합집합(Index Merge) 연산 필요
  • Index Merge 비용이 높아 Full Scan이 더 나을 수 있음

괜찮은 케이스: 동일 컬럼의 OR

SELECT * FROM orders
WHERE status = 'PENDING' OR status = 'PROCESSING'
  • 옵티마이저가 IN ('PENDING', 'PROCESSING')으로 자동 변환
  • 인덱스 활용 가능

우회 방법

1. UNION ALL로 분리

SELECT * FROM users WHERE name = 'kim'
UNION ALL
SELECT * FROM users WHERE email = 'test@example.com' AND name != 'kim'
  • 주의: UNION ALL은 중복 허용 → 조건이 상호 배타적인지 확인 필요

2. 동일 컬럼이면 IN 사용

WHERE status IN ('active', 'pending', 'review')

실무 팁

  • EXPLAIN으로 실제 실행 계획 확인 필수
  • OR 조건이 있는 느린 쿼리 발견 시 위 우회 방법 검토

참고