CS/Database
[MySQL] `NOT IN` vs `NOT EXISTS` 비교 및 권장 방식
clolee
2025. 5. 4. 01:16
✅ NOT IN
vs NOT EXISTS
실무 정리: 차이점, 주의사항, 권장 방식
SQL에서 "어떤 데이터가 다른 테이블에 존재하지 않을 때" 사용하는 대표적인 방법은 다음 두 가지입니다:
NOT IN
NOT EXISTS
하지만 이 두 구문은 겉보기엔 비슷해도, NULL 처리 방식과 실무 안전성 측면에서 큰 차이가 있습니다.
✅ 1. 기본 사용법 비교
🔹 NOT IN
SELECT *
FROM members
WHERE id NOT IN (SELECT member_id FROM ads);
id
컬럼 값이ads.member_id
리스트에 없을 경우만 선택- 비교 대상 컬럼이 반드시 필요함 (
컬럼 NOT IN (리스트)
형태)
🔹 NOT EXISTS
SELECT *
FROM members m
WHERE NOT EXISTS (
SELECT 1
FROM ads a
WHERE a.member_id = m.id
);
ads
테이블에 해당 조건(a.member_id = m.id
)을 만족하는 행이 없을 경우 선택- 행의 존재 여부만 판단, 비교 컬럼 없이도 사용 가능
⚠️ 2. 주의할 점: NULL
이 있을 경우 NOT IN
은 위험
📌 문제 상황
SELECT *
FROM members
WHERE id NOT IN (SELECT member_id FROM ads);
→ 만약 ads.member_id
컬럼에 NULL
값이 1개라도 있으면 전체 결과가 무효화됩니다.
id NOT IN (...)
안에 NULL이 포함되면 항상 FALSE 또는 UNKNOWN- 즉, 모든 결과가 누락될 수 있음
✅ 현재 테이블 상황: 안전한 예외
본 사례에서는 ads.member_id는 FOREIGN KEY로 정의되어 있고 NOT NULL이기 때문에 NOT IN 사용이 안전합니다.
그러나 대부분의 실무 환경에서는 데이터가 완전하다는 보장이 없기 때문에 위험합니다.
✅ 3. 실무 권장 방식: NOT EXISTS
SELECT *
FROM members m
WHERE NOT EXISTS (
SELECT 1
FROM ads a
WHERE a.member_id = m.id
);
NULL
값에 안전하며- 쿼리 옵티마이저가 인덱스를 효율적으로 사용할 수 있음
- 대용량 데이터에서도 일반적으로 성능이 더 우수함
✅ 4. 비교 정리표
항목 | NOT IN |
NOT EXISTS |
---|---|---|
WHERE 뒤에 바로 사용 가능 | ✅ | ✅ |
비교 대상 컬럼 필요 | ✅ 반드시 필요 | ❌ 조건절로 비교 |
NULL 처리 |
⚠️ 위험 (결과 전체 누락 가능) | ✅ 안전 |
의미 | "리스트에 없다" | "해당 행이 존재하지 않는다" |
인덱스 활용 | 제한적 | 최적화 잘 됨 |
실무 추천 | ⚠️ 제한적 사용 | ✅ 적극 추천 |
✅ 5. 결론 및 실무 팁
- 데이터 무결성이 100% 확실할 경우:
NOT IN
도 사용 가능 - 그 외 대부분의 상황:
NOT EXISTS
를 기본 선택하는 것이 안전하고 유지보수에도 유리 - 대량 조인 시에도
NOT EXISTS
가 더 성능 좋은 경우가 많음
이 글은 실무 SQL 작성 시 JOIN
이나 필터링 로직을 짤 때 안전성과 정확도를 높이는 데 도움이 됩니다.