home

Not in을 쓰면 안되는 이유

우선 인덱스 활용이 불가능합니다. 수직탐색이 가능한 IN 과 다르게 수직탐색을 사용할 수 없습니다. 대부분의 B-Tree 인덱스는 특정 값과 같은 데이터를 찾기 위해 정렬되어 있습니다. 그런데 NOT IN 같은 경우는 특정 값이 아닌 나머지 전부를 찾는 쿼리기 때문에, 어디서 부터 스캔을 시작해야하는 지 모릅니다. 즉 스캔 시작점을 알 수 없다가 가장 큰 이유입니다.

따라서 옵티마이저는 수직탐색을 포기하고, Index Full Scan을 하거나, Table Full Scan을 하게 됩니다.

두번째 이유로는 NULL 값으로 인해 범해지는 오류입니다. 만약 NOT IN의 괄호 안에서 직접 입력한 리스트, 혹은 서브쿼리의 결과 중에서 NULL이 하나라도 포함되어있으면 결과는 항상 UNKNOWN으로 처리됩니다. 왜냐하면, NULL은 SQL에서 비어있는 값과 동시에 알 수 없는 상태도 지칭하기 때문에, NOT IN에 NULL이 포함되어있으면 항상 False로 취급됩니다.

이렇게 되면 정상적으로 나와야 할 데이터들도 모두 필터링되어서 쿼리 결과가 단 한 건도 나오지 않게 됩니다.

그럼 뭐써요?

NOT IN보다는 NOT EXISTS를 활용하거나, LEFT JOIN을 써서 Null 값을 체크하는 방식으로 가는 것이 좋을 것 같아요.