성능 개선: N+1 문제 해결과 Fetch Join 전략
AI Store에서 AI코딩으로 만들어진 앱을 만나보세요!
지금 바로 방문하기

성능 개선일지 1 (feat. N+1, Index)

카테고리

프로그래밍/소프트웨어 개발

서브카테고리

데이터 분석

대상자

  • *백엔드 개발자 및 DB 최적화에 관심 있는 개발자**
  • *난이도**: 중급 (N+1 문제, 인덱스 최적화, JPA 쿼리 작성 기술 필요)

핵심 요약

  • N+1 문제 해결을 통해 평균 응답 시간 18.32s → 0.35s로 98% 성능 개선
  • @QueryJOIN FETCH를 사용해 하나의 쿼리로 selections/schedules/events 테이블 연관 조회
  • 인덱스 적용은 schedules 테이블에서 효과 미미, selections 테이블에서는 FK 기반 자동 인덱스 존재

섹션별 세부 요약

1. 문제 진단 및 측정 환경

  • Grafana K6로 20명 동시 사용자, 50번 호출 시 18.38s 평균 응답 시간 측정
  • N+1 문제로 인한 반복 쿼리 발생 (예: `schedules_id=?" 반복 호출)
  • 로그 분석 통해 member.getSelections()s.getSchedule() 호출 시 Lazy Loading으로 N+1 발생

2. N+1 문제 해결

  • JPA FETCH JOIN 쿼리 작성

```java

@Query("SELECT s FROM Selection s JOIN FETCH s.schedule sc WHERE s.member = :member")

List findAllByMemberWithSchedule(@Param("member") Member member);

```

  • 하나의 쿼리로 selections/schedules/events 테이블 연관 조회

```sql

SELECT s1_0.selections_id, s2_0.schedules_id, e1_0.events_id FROM selections s1_0 JOIN schedules s2_0 ON s2_0.schedules_id = s1_0.schedules_id JOIN events e1_0 ON e1_0.events_id = s2_0.events_id WHERE s1_0.users_id = ?

```

  • 성능 개선: 평균 응답 시간 0.35s로 감소

3. 인덱스 최적화 시도

  • selections 테이블: users_id, members_id, schedules_id에 인덱스 생성 (FK 자동 생성으로 효과 미미)
  • schedules 테이블: date, day, time에 인덱스 생성 → 카디널리티 낮음으로 인해 성능 개선 미비
  • 복합 인덱스 시도: date + time, day + timeDB 옵티마이저 판단으로 인해 사용률 낮음
  • 결론: schedules 테이블 인덱스는 효과 미미, selections 테이블은 FK 기반 자동 인덱스로 추가 필요 없음

결론

  • N+1 문제 해결이 성능 개선의 핵심JOIN FETCH 쿼리 사용 권장
  • 인덱스 적용은 카디널리티와 사용 패턴 고려 필수 (예: schedules 테이블 인덱스는 효과 미미)
  • 추가 최적화 방향: DTO Projection, Query DSL, 캐싱, 정규화/비정규화 고려 → 성능 향상의 잠재력 있음