[Spring Boot] FetchJoin + Pagination 문제점

어디든 배우자·2023년 11월 3일
0

문제코드

QueryResults<PostInfo> page = queryFactory
                .selectFrom(postInfo)
                .leftJoin(postInfo.postDetailImages).fetchJoin()
                .orderBy(postInfo.postSeq.desc())
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetchResults();

return new PageImpl<>(page.getResults(),pageable,page.getTotal());

FetchJoin과 Paging을 같이 사용하니 코드는 작동하지만
평소랑 다른 로그를 발견했다.

HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
모든 데이터를 전부 가져와 메모리에서 걸러낸다는 뜻이다. 바로 수정해야한다.

fetchJoin을 2개 이상 사용할 수도 있기 때문에 페이징을
나눠서 조회 후 넣기로 하였다.

해결코드

BooleanBuilder booleanBuilder = new BooleanBuilder();
booleanBuilder.and(postInfo.poplar.eq(PostInfo.Status.valueOf("Y")));

long total = queryFactory
                .select(postInfo.count())
                .from(postInfo)
                .where(booleanBuilder)
                .stream().count();

List<Long> ids = queryFactory
                .select(postInfo.postSeq)
                .from(postInfo)
                .where(booleanBuilder)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .fetch();

List<PostInfo> content = queryFactory
                .selectFrom(postInfo)
                .where(postInfo.postSeq.in(ids).and(booleanBuilder))
                .orderBy(postInfo.postSeq.desc())
                .fetch();

for(PostInfo post : content) {
            List<PostDetailImage> postDetailImages = queryFactory
                    .selectFrom(qPostDetailImage)
                    .where(qPostDetailImage.postInfo.postSeq.eq(post.getPostSeq()))
                    .distinct()
                    .fetch();
  			List<PostThumbnailImage> postThumbnailImages = queryFactory
                    .selectFrom(qPostThumbnailImage)
                    .where(qPostThumbnailImage.postInfo.postSeq.eq(post.getPostSeq()))
                    .distinct()
                    .fetch();
			post.setPostDetailImages(postDetailImages);
            post.setPostThumbnailImages(postThumbnailImages);
}

return new PageImpl<>(content, pageable, total);

긴 쿼리문이 짧아지고, N+1 문제가 사라졌지만 짧은 쿼리문이 많아졌다.
뭔가 임시 방편으로 해결한 느낌.. 조금 더 좋은 방법을 찾아봐야겠다.

profile
다 흡수하기.

0개의 댓글