Rlog

Rails Query 성능 향상기 본문

Ruby On Rails

Rails Query 성능 향상기

dev_roach 2021. 9. 20. 17:34
728x90

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 를 사용하자!