상황
- 댓글 약 1만개
- 댓글 좋아요 약 1만개
- 유저 차단 약 1만개
- 대댓글 약 1만개
주요 조회 데이터 및 조건
- 댓글 10개 조회(limit 10)
- 작성자 정보
- 조회 유저 좋아요 여부 (sub query)
- 받은 좋아요 개수 (sub query)
- 작성자 차단 여부 (sub query)
테스트 조건
- 1초당 100번 요청 5번 수행
- 1초당 500번 요청 4번 수행
- 1초당 100번 요청 2번 수행
개선 전 쿼리 성능
전체 조회 쿼리1(서브쿼리3 + 커버링 인덱스x)
결과
커버링 인덱스 적용 후 쿼리 성능
커버링 인덱스 쿼리1 + 전체 조회 쿼리1(서브쿼리3)
결과
모든 요청에 따른 성능이 눈에띄게 개선 되었다. 특히 처리량과 표준편차의 경우 초당 1000번의 요청에서 크게 개선되었다.
하지만 초당 500번 이상의 요청에서는 평균 1초 이상의 지연시간 및 최대 5초 이상을 보이고 있으므로 아직 개선의 필요성이 보인다.
조회 유저 좋아요 여부 sub query 개선
커버링 인덱스 쿼리1 + 좋아요 여부 제외 전체 조회 쿼리1(서브쿼리2) + 좋아요 여부 조회 쿼리1
개선 방식 - 기존에는 전체 조회 쿼리에서 좋아요 여부를 sub query로 조회하고 있던걸 댓글의 아이디로 새로운 쿼리를 사용해 java 언어에서 각 댓글에 맞는 좋아요 여부 상태를 조합
결과
모든 요청 수에 평균 시간이 개선되었고 1000번 500번 모두 최대 요청 시간 또한 줄어들었다.
처리량과 표준편차 또한 유의미한 개선결과있어보인다.
좋아요 수 sub query 개선
커버링 인덱스 쿼리1 + 좋아요 여부 조회 쿼리1 + 좋아요 수 조회 쿼리1 + 나머지 전체 조회 쿼리1(서브쿼리1)
개선 방식 - 좋아요 여부와 마찬가지로 sub query 로 조회하고 있던 댓글별 좋아요 수를 새로운 개별 쿼리를 이용해 조회 후 java언어로 통해 각 댓글의 좋아요 수를 조합
결과
서브쿼리의 개선에 따라 평균 응답 시간또한 유의미한 개선이 있어보인다. 500번 요청에서는 기대보다 개선점이 없지만 1000번의 요청에서는 처리량, 최대 응답, 평균 응답속도에서 개선이 되었다.
기존 쿼리의 문제점
개선 전 쿼리의 서브쿼리 2개에서의 문제점
- 좋아요 여부 조회 sub query - 조회되는 댓글의 수(10개) 만큼 좋아요 테이블의 해당 멤버의 좋아요 여부를 찾을 때 까지 스캔을 하게된다. 최악의 경우 좋아요 로우 수(약 1만개) 만큼 스캔하여 최대 10만 번의 스캔이 될 수 있다.
- 좋아요 개수 조회 sub query - 해당 쿼리도 마찬가지로 조회 댓글의 수(10개) 만큼 좋아요 테이블을 조회하는데 해당 쿼리는 무조건 좋아요 테이블의 전체를 스캔하게되고 innerJoin(spring query dsl) 으로 탈퇴멤버의 좋아요를 거를 조건까지 붙고 있어 해당 쿼리의 경우 innerJoin과 좋아요 전체 스캔(1만) 이 조회할 댓글 수(10개) 만큼 수행되고 있었다.
최종 결과
- 초당 100 요청 - 평균 요청 시간 약 86% 개선, 초당 처리량 약 130% 증가
- 초당 500 요청 - 평균 요청 시간 약 33% 개선
- 초당 1000 요청 - 평균 요청 시간 약 49% 개선, 초당 처리량 약 250% 증가
전체적인 지표가 대폭 개선된것을 확인할 수 있다.
조회되는 데이터의 칼럼 수가 많고 로우가 많은 경우엔 커버링인덱스 사용을 하면 개선에 큰 도움이 되고
서브쿼리로 조회되는 테이블의 로우가 많은 경우에는 새로운 쿼리로 해당 테이블의 데이터를 조회 후 java 코드로 데이터를 합치는 방식을 사용하므로 개선에 큰 도움이 되는것같다.
하지만 개선을 위해 추가된 쿼리와 java코드 만큼 가독성 및 유지보수에는 단점이 될 수 있다.
*네트워크 환경에 따라 결과의 오차가 있을 수 있음.
'성능 개선' 카테고리의 다른 글
영상 인코딩 및 최적화를 위한 FFmpeg 사용법과 Spring Boot 연동 예제 (2) | 2023.04.28 |
---|---|
[JMeter] JMeter를 이용하여 성능 테스트 (with Spring Boot) (0) | 2022.03.22 |