티스토리 뷰

Latency 3.52s -> 454ms 로 쿼리를 7.7배 개선한 작업을 공유하고자 합니다.

 

문제 상황 & 고민

  • 서비스의 핵심 API의 Latency가  데이터가 몇십만 건이 쌓이는 경우 성능적 개선이 필요했습니다.
  • 해당 API에서 사용하는 DB 조회 쿼리 개선이 필요하다고 판단했습니다.

개선 작업

  • 약 41만 건의 랜덤한 데이터 삽입 이후 K6를 통해 부하테스트를 통한 평균 Latency를 확인하며 진행했습니다.
  • 부하테스트의 경우 같은 조건으로 5번 이상씩 수행하며 평균에 가까운 값을 확인했습니다.

1. 초기 상태 [3.52s]

  • 어떤 작업도 하지 않은 상태에선 조회 API Latency가 3.52초가 걸렸으며, 이로 인해 개선 작업을 시작했습니다.
  • 서비스의 가장 중요한 결과 조회 API 이었기에 더더욱 개선이 필요했습니다.

2. Fetch Join [3.04s]

  • 우선, N+1 이 발생함을 확인해 Fetch Join을 수행했습니다. N+1에서 N은 5 ~ 6 정도였습니다.

3. B-Tree 인덱스 [990.19ms]

  • Join을 수행중이었으며 PostgreSQL은 FK에 인덱스가 자동생성되지 않기 때문에 우선 B-Tree인덱스를 적용했습니다.

4. 시간순으로 생성되는 UUID (ULID 라이브러리) [781.77ms]

  • FK가 UUID 타입임을 고려해 모든 UUID가 정렬되어 생성될 수 있도록 ULID 라이브러리를 도입했습니다.

5. BRIN 인덱스 [454.27]

  • PostgreSQL의 다른 인덱스 중 Block Range Index를 사용했습니다.
  • 해당 인덱스는 블럭을 인덱싱하며 최솟값과 최댓값을 저장하기에 모두 정렬된 값을 인덱싱하기에 적합합니다.
  • 저장공간을 타 인덱스에 비해 적게 사용한다는 이점도 있습니다.

 

 

해결 & 결과

  • 7.7배 빨라진 API로 개선 및 쿼리 횟수 감소
상황 시도 결과 [평균 Latency] 비고
초기 상태 -   3.52s -
JPA의 N+1 문제 발생 Fetch Join 3.04s N+1에서 N은 5~6
PostgreSQL 특성상 FK에
인덱스가 자동 생성되지 않음
FK에 B-Tree 인덱스 990.19ms -
정렬되지 않은 값에 인덱스가 적용됨 시간 순으로 생성되는 UUID
(ULID 라이브러리)
781.77ms 기존 PK는
UUID ver4 사용
보다 효율적인 인덱스 자료구조 존재 BRIN 인덱스 454.27ms Brin 인덱스는
블럭을 인덱싱하며
최솟값과 최댓값 저장

* 표의 상단 부터 차례로 진행했습니다.

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함