컴퓨터일반/DB

[Oracle] NOT IN vs NOT EXISTS 차이점 완벽 정리

G-Ryon 2026. 4. 13. 12:29

오라클 데이터베이스를 다루다 보면 특정 집합에 포함되지 않는 데이터를 찾기 위해 NOT IN과 NOT EXISTS 사이에서 고민하게 됩니다.

겉보기엔 비슷해 보이지만, NULL 처리 방식성능 면에서 큰 차이가 있습니다.

실무에서 실수하기 쉬운 포인트와 예제를 중심으로 깔끔하게 정리해 드립니다.


1. 한 줄 요약

  • NOT IN: 서브쿼리 결과에 NULL이 하나라도 있으면 결과가 나오지 않습니다.
  • NOT EXISTS: 서브쿼리 내의 NULL 여부와 상관없이 조건에 맞는 행의 존재 여부만 따집니다.

2. 예제로 보는 결과의 차이

두 방식의 차이를 확인하기 위해 아래와 같은 샘플 테이블이 있다고 가정해 보겠습니다.

[EMP_DEPT (직원 테이블)]

EMP_ID DEPT_NAME
1 개발
2 디자인
3 기획

[RESTRICTED_DEPT (제한된 부서 테이블)]

DEPT_NAME
개발
NULL

Case A: NOT IN을 사용하는 경우

SQL
 
SELECT * FROM EMP_DEPT
WHERE DEPT_NAME NOT IN (SELECT DEPT_NAME FROM RESTRICTED_DEPT);
  • 결과: 데이터가 조회되지 않음 (0건)
  • 이유: NOT IN은 내부적으로 DEPT_NAME != '개발' AND DEPT_NAME != NULL로 풀립니다. 오라클에서 NULL과의 비교는 항상 Unknown이기 때문에 전체 조건이 만족되지 않습니다.

Case B: NOT EXISTS를 사용하는 경우

SQL
 
SELECT * FROM EMP_DEPT E
WHERE NOT EXISTS (
    SELECT 1 
    FROM RESTRICTED_DEPT R 
    WHERE R.DEPT_NAME = E.DEPT_NAME
);
  • 결과: 디자인, 기획 (2건)
  • 이유: NOT EXISTS는 메인 쿼리의 DEPT_NAME과 서브쿼리의 DEPT_NAME이 일치하는 '행'이 존재하는지만 체크합니다. NULL은 비교 조건(=)에서 일치하지 않으므로 제외되고, 나머지 일치하지 않는 부서들이 정상적으로 출력됩니다.

3. 성능(Performance) 측면

인덱스 활용

  • NOT EXISTS: 일반적으로 Anti-Join 방식으로 동작하며, 서브쿼리 테이블의 인덱스를 효율적으로 활용합니다. 메인 테이블의 행마다 서브쿼리를 확인하다가 조건에 맞는 것을 하나라도 찾으면 즉시 멈추기 때문에 대량 데이터 처리 시 유리합니다.
  • NOT IN: 과거에는 인덱스 활용이 비효율적이었으나, 최신 오라클 버전(11g 이상)에서는 Null-Aware Anti-Join 기술이 도입되어 성능 차이가 많이 줄었습니다. 하지만 여전히 NULL 체크를 위한 내부 연산이 추가될 수 있습니다.

4. 언제 무엇을 써야 할까?

상황 추천 연산자 이유
서브쿼리 컬럼에 NULL이 있을 때 NOT EXISTS NOT IN은 결과를 0건으로 반환할 위험이 있음
서브쿼리 컬럼이 NOT NULL일 때 둘 다 무관 성능 차이가 미미하며 가독성에 따라 선택
가장 안전한 선택을 원할 때 NOT EXISTS 데이터 변화에 유연하게 대응 가능

5. 마무리 요약

오라클에서 서브쿼리를 이용해 제외 조건을 걸 때는 NOT EXISTS를 기본으로 사용하는 습관을 들이는 것이 좋습니다. 서브쿼리 컬럼에 NULL이 하나라도 섞여 들어오는 순간 NOT IN은 의도치 않은 결과를 내뱉어 심각한 로직 오류를 발생시킬 수 있기 때문입니다.


Copyright 2026. [Ryon] all rights reserved.