일기 slecs

파트너 송금 조회 쿼리 리팩터링으로 응답 속도 5배 개선

목차

무엇을 줄였나

파트너 송금 조회 쿼리가 길었음. 같은 조인을 세 번 반복하고 인라인 뷰도 두 개나 끼어 있었음. 화면 하나에 결과 보여주는 게 전부인데 실행계획 떠보면 풀스캔이 두 번 찍혀서 손봐야 했음.

원본 구조를 거칠게 정리하면 이랬음:
- 송금 본 테이블 + 파트너 정보 조인
- 같은 조건으로 수수료 합계 뽑는 서브쿼리
- 환불 차감용 또 다른 서브쿼리
- 셋을 외곽에서 다시 조인해서 합침

읽기도 어렵고 인덱스도 제대로 안 타고 있었음.

단순화 방향

서브쿼리 두 개를 SUM(CASE WHEN) 으로 합치는 패턴으로 바꿈. 기준 테이블 한 번만 훑고 집계 한 방에 끝남.

SELECT
  partner_id,
  SUM(CASE WHEN type='SEND'   THEN amount END) AS send_amt,
  SUM(CASE WHEN type='FEE'    THEN amount END) AS fee_amt,
  SUM(CASE WHEN type='REFUND' THEN amount END) AS refund_amt
FROM transfer_history
WHERE created_at BETWEEN :from AND :to
GROUP BY partner_id

결과

항목 변경 전 변경 후
쿼리 라인 수 약 90 약 35
풀스캔 횟수 2 0
평균 응답 1.4s 0.3s

서브쿼리를 들어내니 (created_at, partner_id) 복합 인덱스가 그대로 먹었음. 별도 힌트도 필요 없음.

배운 점

  • 쿼리 길이는 대개 게으름의 누적임. "일단 돌게" 짠 코드가 그대로 남아 있던 거였음
  • 같은 테이블에 같은 조건으로 두 번 이상 들어가는 서브쿼리는 거의 항상 CASE 집계로 접을 수 있음
  • 실행계획 한 번 안 보고 머지된 쿼리가 제일 무서움. 리뷰에 EXPLAIN 결과 첨부 룰을 추가해야 할 듯
  • 리팩터링 PR은 결과 수치를 꼭 본문에 박아둠. 나중에 누가 다시 풀어버리는 걸 막는 가장 싼 방어선임

안 건드린 것

실제 송금/정산 로직은 손 안 댔음. 조회 한 화면만 정리. 비즈니스 룰이 바뀌는 리팩터는 PR을 따로 끊는 게 안전함. 한 번에 묶으면 롤백 단위가 너무 커지고, 문제가 터졌을 때 원인 분리도 어려워짐. 조회 정리 → 도메인 정리 순으로 가는 게 결국 빠름.

다음

댓글 0

첫 댓글 달아줘.