Rails 특정 부분에서 Where + Count 말고 Exist? 를 써야 하는 이유
우리가 기존의 쓰던 중복로직 검사를 하던 코드는 아래와 같다.
where(condition).count 조합
위와 같은 로직을 작성하면 돌때 아래와 같은 쿼리가 나간다.
차이점?
저 위의 로직으로만 보면 언뜻 비슷해보이나 크나큰 차이가 있다. 아래와 같은 예시를 보자
예약 스케쥴과 - 예약에 관한 예약정보를 읽어온다고 해보자.
전제 조건은 아래와 같다 하나의 예약에는 여러가지 예약 일정이 걸려있을 수 있다.
하나의 배송에는 여러가지 주문이 걸려있을 수 있다. 예를 들면 아래와 같은 상태일것이다.
만약 여기서 1번 쿼리 where(:reservation_id => 1).count query 를 날려본다고 해보자.
위와 같이 세개를 전부 순회하게 될것이다. 즉 나는 단순히 예약1로 만든 예약일정이 있는지만 확인하고 싶을 뿐인데 1,2,3 을 전부 조회해야 하는 일이 생긴다. 왜냐하면 COUNT Query 이기 때문이다.
지금의 상황에서는 굳이 3개를 전부 조회하는 것이 아닌, 1개만 조회해도 예약이 있다는 것을 알기 때문에 다른 선택지를 고르는게 좋을것이다.
원래 SQL 이 권장하는 중복체크 방법은 COUNT 가 아닌 아래와 같은 EXIST 쿼리이다.
SELECT EXIST (SELECT 1 FROM reservation_schedule WHERE reservation_id = 1)
실제로 explain 이나 실행 속도를 차이를 내봐도 성능상으로 같으며, 위와 같은 특정경우에는 훨씬 더 빠르다.
검색하다 보니 정리가 잘 된 글 하나가 있어서 아래에 링크로 적어두겠다.
https://blog.jooq.org/avoid-using-count-in-sql-when-you-could-use-exists/
문제점
하지만 Rails 에서 저걸 계속해서 써주기에는 너무 부담스럽고 만들어야 하기 쉽지 않다.
따라서 다른 대안을 찾아야 한다.. 라고 하고 싶은데 이미 Rails 에 찾아보니 있었다.
exists? 이용
위와 같은 로직을 작성하면 아래와 같은 쿼리가 나간다
EXIST 를 쓰지는 않지만 limit 1 쿼리가 걸려서 나간다. 즉 위의 EXIST 쿼리와 별반 차이가 많이 없다. 해당 쿼리를 아까 예약 쿼리로 가져온다고 해보자
SELECT 1 AS one FROM 'reservation_schedule' WHERE (reservation_id = 1) limit 1
위와 같은 쿼리는 아래와 같이 수행될것이다.
굳이 두 뎁스를 더 들어가진 않는다. 위와 같은 차이는 중복 / 확인 검사 쿼리가 복잡해질수록 더 많은 성능 차이를 유발해 낼수 있다. 그러니 앞으로는 어지간해서 exists 를 사용하자!