SELECT *
FROM person p
WHERE p.id NOT IN ( ... )

NOT IN 쿼리는 부정 포함 조건절로 검색 시 제외할 때 사용 된다.

그런데, 이 부정 조건은 대부분의 DBMS에서 전체 데이터나 테이블을 스캔한 후 조건에 맞지 않는 레코드를 필터링 하기 때문에 테이블 풀스캔을 유발하고 이는 슬로우 쿼리가 될 여지를 준다.

그럼 이 NOT IN 쿼리의 단점은 무엇이 있을까?

NOT IN 쿼리의 문제점

1. 범위를 명확히 정할 수 없다.

IN 절은 특정 값의 목록을 의미한다. 그렇기에 옵티마이저는 “이 값들만 보면 된다”라고판단해 인덱스 탐색을 쉽게 할 수 있다.

하지만, NOT IN 절은 “이 값들을 제외한 모든 값”을 의미하기 때문에 데이터 풀스캔을 하는 경우가 많다.

그리고 이러한 테이블 풀스캔은 성능저하의 요인 중 하나이다.

2. NULL 처리에 문제가 있다.

SELECT *
FROM person p
WHERE p.id NOT IN ( SELECT a.id FROM address a)

여기서 주소의 id가 null인 레코드가 하나라도 있다면 p.id ≠ null이 되는데 이는 비교 불가로 전체 조건이 UNKNOWN이 되어 결과가 제대로 나오지 않을 수 있다.

3. 범위 연산을 사용할 수 없다.

인덱스는 일반적으로 범위 조건(ex: BETWEEN, <, > 등)에 유리하다.

하지만 NOT IN은 여러 개의 != 조건을 합친 것과 비슷한 구조라 범위 필터링이 어렵다.