쿼리 성능 개선 (1) ‐ 쿼리 검토 - YJGwon/connectruck GitHub Wiki

현재 모든 DB 접근을 Spring Data JPA로 처리했으며 native query가 아닌 query method로만 처리했기 때문에 기능 실행 시 발생하는 쿼리에 대한 점검이 필요하다. 또한 조회 성능을 위해 index가 필요한 column을 찾아야 한다. 각 서비스 기능 별로 통합 테스트를 실행해 발생하는 쿼리들 중 아래 두 case를 중심으로 성능 검토가 필요한 쿼리들을 찾아보았다.

  1. 추가 쿼리 발생
  2. 조건절에 index 없는 column 포함

추가 쿼리 발생

이 항목의 쿼리들은 JPA에서 최적화 해볼 수 있다. 연관 관계를 점검하고 query 생성 방식을 변경하거나, batch size 등의 JPA option 설정을 변경하는 방법이 있다.

PushSubscription

  • deleteByTokenAndTruckId
    • token, truckid로 바로 delete하지 않고 token, truckId로 조회한 후 JPA transaction commit할 때 delete 쿼리 발생
    • 사용되는 기능: 구독 해제

OrderInfo

  • 조회 후 orderLines 접근
    • OrderLine의 목록 조회 쿼리 추가 발생
      • 현재는 OrderLine 안의 OrderInfo 접근하지 않으나 그럴 경우 N + 1 문제 발생
    • 사용되는 기능: 사장님 주문 단건 상세 조회, 주문자 주문 단건 상세 조회

조건절에 index 없는 column 포함

이 항목의 쿼리들에 대해서는 indexing을 고려해봐야 한다. 실행 계획을 확인하고 조건절을 수정해 index를 사용하도록 만들거나, 새로운 index를 추가할 수 있다.

Account

  • findByUsername
    • 사용되는 기능: 회원 가입 시 중복 검사, 로그인
  • findByPhone
    • 사용되는 기능: 회원 가입 시 중복 검사

PushSubscription

  • findByTokenAndTruckId
    • token에 index X
    • 사용되는 기능: 주문 알림 구독 시 중복 검사, 주문 알림 발송, 주문 알림 구독 해제(deleteByTokenAndTruckId)

OrderInfo

  • findByTruckIdAndStatus (order by createdAt)
    • status, createdAt에 index X
    • 사용되는 기능: 사장님 주문 상태별 목록 조회

기타 검토가 필요한 부분

Paging 시 offset 사용

  • limit ?, ?로 조회할 시 시작 값을 찾기까지 모든 row를 처음부터 탐색
  • index 사용해도 마찬가지
  • offet 커지면 성능 저하

OrderInfo 저장 시 OrderLine insert 쿼리 n개 발생

  • batch insert 적용 검토해볼 수 있음

What’s Next?

개선이 필요할 것으로 보이는 쿼리들을 찾았다. slow query log도 좋은 힌트가 될 수 있었겠지만 현재 배포되어있는 서비스 DB에는 데이터가 많지 않아 성능 병목을 감지하기 힘들다. 따라서 충분한 dummy data를 준비해 실질적인 쿼리 성능 측정을 해야 한다. 이렇게 측정한 실행 시간과 DB의 실행 계획을 기반으로 Application에서 발생하는 쿼리에 대한 개선과 index 개선을 진행할 예정이다(주문 조회 쿼리의 개선이 시급하다...).