[Spring JPA] Count 최적화 하기

YoungHo-Cha·2022년 5월 13일
5

운동 매칭 시스템

목록 보기
15/17

오늘은 서비스를 진행하면서 어떤 엔티티에 대한 개수를 조회해야하는 기능을 구현하면서 공부한 내용을 기록한다!

목차

  • 요구사항
  • JPA
  • QueryDsl
  • JPQL

요구사항

먼저 구현하려는 내용을 알아보자!

  • 구현하려는 기능은 "현재 참가 가능한 방 개수 조회"이다.
  • 참가 가능한 방이란
    • 방 시작 시간이 현재 시간보다 미래여야 한다.
    • 방 참가 인원이 최대 인원보다 작아야 한다.

JPA

사실 상 가장 쉬운 방법이다.
방법이 총 2개가 존재한다.

  1. 조회를 하고, return 되는 List의 size를 구하면 되는 것이다.
    하지만 해당 방법은 조회를 Entity 그 자체를 하는 것이 된다.
    성능상 좋지 못하다.(엔티티의 개수가 증가할 수록 성능 Bad)

  2. CountBy 함수를 사용한다.
    이 방법을 쓰면 실제 Query에서의 "Count(-)" 함수를 쓰는 것이다. 그럼 사용해보자.

// 파라미터의 시간보다 "StartAppointmentDate"가 뒤에 있는것 조회
Long countByStartAppointmentDateAfter(LocalDateTime date);

이렇게 했을 때 생성되는 query를 살펴보자.

정상적으로 가능!

But..

이제 전체 인원 > 참여 인원인 부분을 조건 절로 추가해야 한다.

그래서 생각한 메서드이름

Long countByStartAppointmentDateAfterAndLimitPeopleCountGreaterThanParticipantCount(LocalDateTime date);

너무 길긴 하지만.. 프로젝트 빌드가 안된다.

이유는?
GreaterThan 다음에 ParticipantCount가 있으면 안된다. 파라미터로 들어와야 하는 것이다.

맞다. 엔티티 내의 값들은 계산할 수가 없는 것이다.....
(방법을 찾아보았지만.. 모르겠다)

room Entity 내의 값들을 비교해서 조회하는 방법좀 알려듀세요.. 키워드라두..


QueryDsl

그럼 QueryDsl에 지원해주는게 있을까? 찾아보았다.

다음 사진을 보면

더이상 fetchCount() 함수가 사용되지 않는다고 한다.

부족한 실력으로 번역을 해봤더니, QueryDsl로 여러가지의 조건 때문에 (having 절과 같은) count를 구체적으로 반영할 수 없다고 한다. 그래서 실행되는 내용이 단순 조회 후 size() 연산과 같다고 한다.

결국 단순 JPA를 이용하는 것과 똑같다.


JPQL

여러가지 자료를 찾아보았을 때, 많은 사람들이 JPQL을 직접 사용하더라. 자료 시간을 보니 다 최신이다.

직접 Query를 작성하고 Repository에 추가하자!

@Query("SELECT COUNT(*) FROM Room a WHERE DATE(Now()) < DATE(a.startAppointmentDate) AND a.limitPeopleCount > a.participantCount")
    Long getAvailableRoomCount();

해당 방법이 가장 주된 방법인 듯 하다.

근데 Query를 개발자가 직접 써둔 것이 너무나 마음에 걸린다.

꼭꼭 JPA의 2번으로 성공시켜보자.(이름 줄이는 방법도..)


성능 비교

이건 단순한 궁금증이다. 뭐가 더 빠를까? 싶어서 초를 세보았다.

JPA

JPQL

둘 다 29ms가 나온다.

때때로 다르지만 10~50 사이로 나온다.

사실상 차이가 없지 않은가?

누가 승리?

하지만 개발적으로 보았을 때 뭐가 좋을까?

내가 느끼고 아는대로 써보자면 장단점이 다음과 같다.

  1. JPA
    • ORM을 이용해서 컴파일 단계에서 에러가 터진다.
    • 메서드 명이 길어질 수 있다.
    • 단순 쿼리와는 다르게 쿼리 표현에 대한 한계가 존재한다.
  2. JPQL
    • 컴파일 단계에서 에러가 터지지 않는다.
    • 메서드 명을 자유롭게 설정할 수 있다.
    • 표현에 대한 한계가 없다.
    • 개발자가 직접작성하는 쿼리라서 실수가 존재할 수 있다.

이 두가지 방법중 뭐가 좋은지는 나도 잘 모르겠다.

나중에 이런 결정을 내리는 순간이 올 것 같은데, 그때의 회사 시니어 분들께 물어봐야지~~~

profile
관심많은 영호입니다. 궁금한 거 있으시면 다음 익명 카톡으로 말씀해주시면 가능한 도와드리겠습니다! https://open.kakao.com/o/sE6T84kf

0개의 댓글