작성
·
2.1K
·
수정됨
15
searchPageSimple()
: 조회 쿼리와 카운트 쿼리를 한번에 실행
searchPageComplex()
: 조회 쿼리와 카운트 쿼리를 분리
QueryDSL 5.0.0부터는 fetchResults()
와 fetchCount()
를 deprecated 메서드로 공지함에 따라, 강의 내용처럼 searchPageSimple()
과 searchPageComplex()
를 구분해서 구현할 필요 없이 searchPageComplex()
의 방식으로만 구현하면 됨.
@Override
public Page<MemberTeamDto> searchWithPaging(MemberSearchCond cond, Pageable pageable) {
// 데이터 조회 쿼리 (페이징 적용)
List<MemberTeamDto> content = queryFactory
.select(
new QMemberTeamDto(
member.id.as("memberId"),
member.username,
member.age,
team.id.as("teamId"),
team.name.as("teamName")
)
)
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(cond.getUsername()),
teamNameEq(cond.getTeamName()),
ageGoe(cond.getAgeGoe()),
ageLoe(cond.getAgeLoe())
)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
// count 쿼리 (조건에 부합하는 로우의 총 개수를 얻는 것이기 때문에 페이징 미적용)
Long total = queryFactory
.select(member.count()) // SQL 상으로는 count(member.id)와 동일
.from(member)
.leftJoin(member.team, team)
.where(
usernameEq(cond.getUsername()),
teamNameEq(cond.getTeamName()),
ageGoe(cond.getAgeGoe()),
ageLoe(cond.getAgeLoe())
)
.fetchOne();
return new PageImpl<>(content, pageable, total);
}
이 때, total
을 아래와 같이 구할 수도 있지만
long total = queryFactory
.selectFrom(member)
.leftJoin(member.team, team)
.where(
usernameEq(cond.getUsername()),
teamNameEq(cond.getTeamName()),
ageGoe(cond.getAgeGoe()),
ageLoe(cond.getAgeLoe())
)
.fetch() // 조건에 부합하는 전체 데이터를 조회 (List)
.size(); // List의 길이로 total을 구하기
count 함수는 SQL 차원에서 지원하기 때문에 굳이 이렇게 전체 데이터를 받아온 뒤에 애플리케이션 레벨에서 별도로 size()
를 호출해서 구할 필요 없고, 처음부터 카운트 쿼리를 호출하는 것이 나음.
이유는 전체 데이터를 불러오고 나서 size()
로 구하는 방식은 영속성 컨텍스트에 데이터를 전부 받아온 뒤에 개수를 따로 세는 것이기 때문에 불필요하게 메모리를 잡아먹기 때문.
total
을 구하는 방식에 대한 내용은 강의에 언급되지 않았기 때문에 제가 따로 검색해보고 내린 결론입니다. 제가 생각한 것이 맞는지 궁금합니다.
이외에도 잘못된 부분이 있다면 지적해주시면 감사하겠습니다.
답변 1
8
안녕하세요. 이현준님
생각하신 내용이 정확하게 맞습니다^^
추가로 Querydsl 5.0과 무관하게 size()를 사용하면 안됩니다! 이것은 성능상 네트워크를 통한 데이터 전송이 매우 많기 때문에 OOM 장애로 이어질 수 있습니다. 데이터가 1000만 건이라면 성능도 문제이지만 메모리에 다 올리지 못하고 바로 장애가 발생하겠지요?
감사합니다.
답변 감사합니다! 좋은 강의 제공해주신 덕분에 재미있게 학습하고 있습니다 👍🏻