문제 1 : 50,000개 이상에 대한 모임 전체 조회 시, 시간이 30~50초 이상 걸리는 문제

QueryDsl 33초.png

원인: Meeting Entity의 fetchType이 Eager로 설정

→ meeting 조회시, meeting_member를 모두 조회하면서, 조회 시간 증가

Eager.png

Lazy.png

해결: Lazy로 변경 → 5~10초로 단축

QueryDsl 이거삭제.png


문제 2 : 5~10초로 단축했으나, 이것 역시 너무 길다고 판단

⇒ leftJoin으로 2개의 테이블과 연결한 뒤, 중복되는 id를 distinct로 지우는 방식

/* 모임 조회 */
@Override
public Slice<Meeting> getMeetingSlice(Double locationLat, Double locationLng, List<Long> skillId, List<Long> careerId, Pageable pageable) {
    List<Meeting> meetingList = queryFactory
            .selectFrom(meeting)
            .distinct()
            .leftJoin(meeting.skills, meetingSkill)
            .leftJoin(meeting.careers, meetingCareer)
            .where(
                    skillEq(skillId),
                    careerEq(careerId)
            )
            .orderBy(
                    distanceExpression(locationLat, locationLng).asc()
            )
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize() + 1)
            .fetch();

    return new SliceImpl<>(meetingList, pageable, hasNextPage(meetingList, pageable.getPageSize()));
}

private BooleanExpression careerEq(List<Long> careerId) {
    return careerId == null || careerId.isEmpty() ? null : meetingCareer.career.Id.in(careerId);
}

private BooleanExpression skillEq(List<Long> skillId) {
    return skillId == null || skillId.isEmpty() ? null : meetingSkill.skill.Id.in(skillId);
}

private ComparableExpressionBase<Double> distanceExpression(Double locationLat, Double locationLng) {
    return Expressions.numberTemplate(Double.class,
            "ST_DISTANCE_SPHERE(point({0}, {1}), point(meeting.locationLng, meeting.locationLat))",
            locationLng, locationLat);
}

예상 원인

1. Where 절에서 IN 연산자를 사용하여, table scan이 IN절에 해당하는 인자 수 만큼 발생하는지

⇒ Where절을 제외한 뒤, Skill Id List와 Career Id List를 확인하지 않더라도 동일하게 오래 걸림

@Override
public Slice<Meeting> getMeetingSlice(Double locationLat, Double locationLng, List<Long> skillId, List<Long> careerId, Pageable pageable) {
    List<Meeting> meetingList = queryFactory
            .selectFrom(meeting)
            .distinct()
            .leftJoin(meeting.skills, meetingSkill)
            .leftJoin(meeting.careers, meetingCareer)
            .orderBy(
                    distanceExpression(locationLat, locationLng).asc()
            )
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize() + 1)
            .fetch();

    return new SliceImpl<>(meetingList, pageable, hasNextPage(meetingList, pageable.getPageSize()));
}

Untitled