현재 구조로는 Custom Repository Implementation을 사용 중

많은 필터가 쿼리문에 들어가기 때문에 기본적으로 제공하는 JPA를 사용할 수 없게 되어 사용하게 되었습니다.

 

문제점

 

전체를 select해서 조회하는 쿼리를 작성

전체 데이터와 전체 개수를 count하는 2개의 쿼리를 생성

 

아래코드는 where절을 뺀 코드 입니다. 상황에 맞게 추가하시면 될 것 같습니다.

필터값에 맞는 데이터를 List로 출력, 전체 데이터의 개수 2가지를 출력하는 메서드 입니다.

 

CustomRepositoryImpl.java

List<AllDataEntity> allDataEntities = jpaQueryFactory
        .selectFrom(qAllDataEntity)
        .offset(pageable.getOffset())
        .limit(pageable.getPageSize())
        .fetch();

long contentCount = jpaQueryFactory
        .from(qAllDataEntity)
        .fetch().stream().count();

 

 

위와 같이 데이터를 조회하니 2초가량이 나옵니다.

코드를 보고 문제점을 파악하신 분들도 있을 수 있습니다.

 

하나하나 짚어보겠습니다.

 

1. fetch().stream().count()

 

  • fetch()는 조건에 맞는 데이터를 전부 DB에서 가져와 메모리로 로드하며,
  • stream().count()는 이 메모리상에 로드된 데이터에서 조건에 맞는 항목을 계산하여 개수를 반환합니다.

즉, 정리하면 데이터 전체를 DB에서 가져와 메모리 로드 후 계산을 진행하는 방식

메모리 사용량이 증가, 성능저하 발생 우려

 

 

long contentCount = jpaQueryFactory
        .select(qAllDataEntity.count())
        .from(qAllDataEntity)
        .fetchOne();

if (contentCount == null) {
    contentCount = 0L;
}
// null처리는 센스 ㅎㅎ

 

 

2. count()

 

  • DB에서 직접 데이터를 세는 방법이며, 1번과 다른점은 DB에서 직접 가져오는 방식이기 때문에 메모리 사용량을 감소할 수 있습니다!

 


 

추가로 fetch는 리스트로 값이 반환되기 때문에 2번씩 같은 함수에서 사용하는 건 메모리 낭비와 DB과부하의 우려가 있습니다.

 

필터값과 상관없이 저는 DB에 저장된 모든 개수를 구해야 하기 때문에 fetchOne을 사용하여 count값만 나타내주었지만

fetch에서 출력된 값을 .size()함수를 사용하여 그대로 뽑아내는 것도 방법입니다.

long contentCount = allDataEntities.size();

 

 

+ Recent posts