
실제로 JPA를 개발하면서 AOP를 이용해 데이터 성능을 측정한 후 결과를 바탕으로 작성된 글 입니다.
실제로 성능 최적화를 할 수 있는 방법은 4가지가 있다.
- 1) 스칼라 타입으로 조회
- 2) 읽기 전용 쿼리 힌트 적용
- 3) 읽기 전용 트랜잭션 사용
- 4) 트랜잭션 밖에서 읽기
실제로 4가지 모두 사용해본 결과 2번과 3번이 가장 효과가 좋았다.
스칼라 타입이나 트랜잭션은 모두 트랜잭션의 영향을 받지 않는데 , 3번의 읽기 전용 트랜잭션을 사용하면 변경 감지에 해당되지 않아 메모리를 최적화 할 수 있었다.
다만 메모리는 차이가 있었지만 속도상으로는 큰 차이는 없었다.
Service 최적화 :
@Transactional(readOnly = true) // 읽기 전용 트랜잭션 ReadOnly 추가 public class ReadContentService { public List<FreeCommit> getCommit(Long postId) { return post.getCommit(postId); }
Repository 최적화 :
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly" ,value = "true")) // 읽기 전용 쿼리 힌트 적용 @Query("SELECT c FROM FreePost p join p.freeCommit c where p.numbers = :postNumber") List<FreeCommit> getCommit(@Param("postNumber") Long postNumber);
실제 1000개의 데이터를 기준으로 서버 요청시간을 비교해 보았다. ( 10번의 요청 기준 )
최적화전 DB요청 시간 : 71.1ms
최적화 후 요청시간 65.8ms
메모리 차이는 눈에 띄는 반면 요청 시간은 별 차이가 없다.
데이터가 1000개가 넘어가면 전체 페이지를 로딩하고 클라이언트에서 페이징하는것과 서버쪽에서 해당 페이지에 데이터를 나눠서 보내주는 차이를 계산해 보았다.
Controller 코드 : @Query(value = "JPQL쿼리") public List<ReturnPostDataDTO> getPostData(Pageable pageable);
JPA Spring Data 에서 제공하는 org.springframework.data.domain.Pageable 를 매개변수로 넘겨주어 요청 url를 page=번호&size=20 으로 페이지를 나눴다.
500개 데이터
페이징 사용하기전 : 54ms , 42ms , 98ms , 112ms , 95ms
페이징 사용한 후 : 11ms , 15ms , 6ms , 5ms , 8ms
1000개 데이터
페이징 사용 전 : 54ms , 46ms , 104ms , 47ms , 40ms
페이징 사용 후 : 2ms , 4ms , 5ms , 4ms , 4ms
실제로 10개씩 나눠 데이터를 요청을 했을 때 효과가 빠르게 나타났다. 하지만 페이징을 할 때 무조건 좋은것은 아니였다. 컨텐츠에 따라 무한스크롤 을 사용해야 할 때가 있어서 무조건 사용하라는 것은 아니다.