airbnb 클론 프로젝트를 하면서, 내가 원하는 체크인 - 체크아웃 기간 동안에 예약 가능한 숙소를 찾기 위한 쿼리를 작성해야 했다. 이때 테이블은 다음과 같았다.
place {
place_id,
...
}
reservation {
reservation_id,
place_id,
check_in,
check_out,
...
}
여기서 원하는 체크인 - 체크아웃 기간 동안 예약할 수 있는 장소를 찾기 위해서 다음과 같은 쿼리를 작성하였다.
SELECT ... FROM place WHERE place_id NOT IN (SELECT place_id FROM reservation WHERE 조건);
스택 오버플로우에서 찾은 것인데, 서브쿼리를 이용하여 먼저 원하는 기간 동안에 예약하지 못하는 예약들에 대해서 찾은 후, NOT IN
을 이용하여 포함하지 않은 결과들을 선택하는 쿼리이다. 내용 자체는 매우 직관적인 쿼리이지만, 서브쿼리를 사용하는 경우에 성능이 좋지 못할 수 있다고 한다.
그래서 관련 이야기를 찾아봤는데, MySQL의 경우, NOT IN
은
의 방식으로 최적화를 진행한다고 한다. MySQL 5.7 문서지만, 8.0에도 거의 비슷한 내용이 담겨있다.
SELECT ... FROM place p LEFT JOIN reservation r on p.place_id = r.place_id AND 조건 WHERE r.reservation_id IS NULL;
한편, 서브쿼리의 경우 왠만하면 조인으로 해결할 수 있다고 하고, 그 경우가 성능도 더 뛰어나다고 한다. Real MySQL에서, NOT IN
은 위와 같은 조인 쿼리로 바꿀 수 있다고 한다.
간단히 설명하면, 조건
에 맞는 reservation을 place에 조인하고서, WHERE
절로 조인이 되지 않은 결과만을 가져오는 것이다.
이와 관련해서 여러가지 찾아보는 중에, 차집합 구하기, 어떤 쿼리가 좋을까? 라는 글을 보게 되었다. 근데 아직 DB / SQL에 대해서 이해가 부족하여 읽어보기만 하였다. 오래된 글이기도 하고, 현재의 MySQL와 MS SQL하고는 다를 수도 있다. DB / SQL을 좀 더 공부해야겠다.