-
OR 옵션조건과 OR ExpansionTIL 2025. 6. 7. 15:05
OR 조건
SQL에서 둘 중 하나 이상의 조건이 참일 경우에 해당 레코드를 선택하기 위해 사용되는 조건
옵션 조건 처리 방법
OR 을 사용한 조건 처리 방법은 다음과 같다.
1. 인덱스 엑세스 조건으로 사용 불가
2. 인덱스 필터 조건으로도 사용 불가
3. 테이블 필터 조건으로만 사용 가능
해당 사항을 하나씩 알아보자.
1. 인덱스 엑세스 조건으로 사용 불가 에 대하여..
[인덱스 엑세스 조건 = 범위조건이 나오기 전 인덱스 컬럼까지] 를 말한다.
만약, 선두 컬럼에 범위조건에 해당하는 OR 조건이 위치한다면? -> 뒤의 인덱스 컬럼은 전부 필터 조건으로 변하여 인덱스를 구성해도 이를 사용 할 수 없다.
2. 인덱스 필터 조건으로도 사용 불가 에 대하여..
인덱스 스캔 단계에서 필터링해도 비효율적인데, 테이블 엑세스 단계에서 필터링한다라는 것은 OR 옵션 조건으로 처리한 컬럼을 인덱스에 포함할 필요조차 없다는 것을 의미한다.
장점
옵션 조건 컬럼이 NULL 허용 컬럼이더라도 결과집합을 보장한다의 의미..
이말의 뜻은 뭘까?
WHERE 조건에 들어가는 어떤 컬럼이 NULL일 수도 있어도,
우리가 원하는 데이터를 정확히 빠짐없이 가져올 수 있다는 뜻이다.ex. 다음과 같은 직원 테이블이 있다고 가정하자
이름 부서 직급 철수 영업부 대리 영희 인사부 과장 민수 NULL 차장 수진 마케팅부 NULL 해당 테이블을 조회 할 때 다음 조건을 주면 직급이 NULL인 수진은 조회되지 않는다.
WHERE 부서 = '영업부' OR 직급 = NULL
- 직급 = NULL → 이건 항상 조건이 참도 아니고 거짓도 아님 (SQL에서 NULL = 뭔가는 무조건 UNKNOWN)
- 그래서 직급이 NULL인 사람은 아예 검색이 안됨!
- 수진은 조회되지 않는다
다음 쿼리는?
WHERE (:직급 IS NULL OR 직급 = :직급)
- :직급이 NULL이면 → 조건은 항상 참이 돼서 모든 직급 포함됨
- :직급이 값이면 → 해당 직급만 필터링
따라서, 성능은 느리더라도 우리가 원하는 데이터를 정확히 빠짐없이 가져올 수 있다
OR Expansion 개념?
'OR Expansion'은 SQL에서 OR 조건을 포함한 쿼리를 성능 최적화를 위해 여러 개의 쿼리로 분해하는 기법이다. 이 기법은 주로 오라클 옵티마이저가 자동으로 수행하거나, 개발자가 수동으로 UNION ALL 등을 이용해 적용하기도 한다.
ex1.
SELECT * FROM employees WHERE department_id = 10 OR job_id = 'IT_PROG';
해당 쿼리는 department_id 와 job_id 를 인덱스로 가지고 있는 테이블을 참조한다. 한 쿼리에는 하나의 인덱스만 사용 가능하므로, 해당 쿼리는 Full table scan 을 수행한다.
SELECT * FROM employees WHERE department_id = 10 UNION ALL SELECT * FROM employees WHERE job_id = 'IT_PROG' AND department_id <> 10;
OR Expansion 을 사용하면 다음과 같이 표현 가능하다.
* UNION ALL 은 중복제거를 하지 않으므로 성능상 유리
* 하지만, 중복데이터가 제거되지 않는다는 문제 발생
* department_id <> 10 을 사용하여 중복 데이터 발생하지 않도록 보완
언제쓸까?
1. OR 조건 각각에 인덱스가 있을 때
- WHERE col1 = 'A' OR col2 = 'B' 형태에서 col1, col2 둘 다 인덱스가 있을 때.
- OR을 그대로 사용하면 옵티마이저가 한쪽 인덱스만 사용하거나, 풀 테이블 스캔할 가능성이 큼.
- OR Expansion을 사용하면 각 조건을 분리된 쿼리로 실행하여 각각 인덱스를 사용할 수 있음.
2. 대량의 데이터에서 성능 이슈가 발생할 때
- OR 조건이 복잡하거나 조건이 많고 데이터가 큰 경우,
- OR을 그대로 사용하면 풀 테이블 스캔이 발생해서 성능이 매우 저하됨.
- 각 조건을 나눠서 별도로 실행하면 실행 계획이 훨씬 효율적임.
3. 옵티마이저가 자동 OR Expansion을 안 할 때
- Oracle 옵티마이저는 자동 OR Expansion을 하기도 하지만, 복잡하거나 통계가 불완전할 경우 제대로 수행하지 못함.
- 이럴 땐 개발자가 수동으로 분리해서 UNION ALL을 써줘야 함.
어떻게 사용할까?
옵티마이저가 자동으로 수행을 하지 않을 경우, 다음과 같은 힌드를 통해 제어 가능하다.
1. use_concat
OR Expansion 을 유도하고자 할 때.
SELECT /*+ use_concat*/ * FROM employees WHERE department_id = 10 OR job_id = 'IT_PROG';
2. no_expand
기능을 방지하고자 할 때
SELECT /*+ no_expand */ * FROM employees WHERE department_id = 10 OR job_id = 'IT_PROG';
'TIL' 카테고리의 다른 글
인덱스 스캔 효율화 (0) 2025.06.06 20240324 DFS (0) 2025.03.24 0320 중복순열 구하기_DFS (0) 2025.03.20 20240225 (0) 2025.02.25 1013 (0) 2024.10.13