인프런 커뮤니티 질문&답변
안녕하세요 FetchGroups에서 Multiset방식 사용하면 어떤가 해서 물어봅니다
작성
·
18
0
안녕하세요 공부하다가 보니
FetchGroups방식으로 했을때 Map으로 반환되고 DTO로 변환해야하는 오버헤드가 발생하는데요
Multiset방식으로 하면 1:N 관계에서 바로 DTO로 반환 할 수 있는데요
코드 보기가 조금은 더 복잡해 보이지만 WHERE절이 있을때 현재 테이블 데이터와 인덱스 상으로는 성능적으로 더 괜찮은거 같아서 multiset방식은 강의에 없어서 어떤지 궁금해서 여쭤봅니다
public List<ActorFilmography> findActorFilmographyWithMultiset(ActorFilmographySearchOption searchOption) {
final JFilmActor FILM_ACTOR = JFilmActor.FILM_ACTOR;
final JFilm FILM = JFilm.FILM;
return dslContext.select(
ACTOR,
DSL.multiset(
DSL.select(FILM.fields())
.from(FILM)
.join(FILM_ACTOR)
.on(FILM.FILM_ID.eq(FILM_ACTOR.FILM_ID))
.where(
FILM_ACTOR.ACTOR_ID.eq(ACTOR.ACTOR_ID),
containsIfNotBlank(FILM.TITLE, searchOption.getFilmTitle())
)
).convertFrom(r -> r.into(Film.class))
)
.from(ACTOR)
.where(
containsIfNotBlank(ACTOR.FIRST_NAME.concat(" ").concat(ACTOR.LAST_NAME), searchOption.getActorName())
)
.fetch(record -> new ActorFilmography(
record.value1().into(Actor.class),
record.value2()
));
}WHERE 조건 포함 시 성능 비교
fetchGroups 방식 (cost=405, rows=609)
Film 필터링 먼저 → FilmActor 조인 → Actor 필터링
1. film 테이블 스캔 (1000 rows)
└─ LIKE '%COMMANDMENTS EXPRESS%' → 111 rows
2. film_actor 인덱스 조회 (idx_fk_film_id) → 609 rows
3. actor PRIMARY KEY 조회 → 609 rows
└─ LIKE '%LOLLOBRIGIDA%' → 1 row (최종)
특징:
- Film 조건이 선택적이면 먼저 필터링하여 조인 범위 축소
- 하지만 Actor 필터링은 마지막에 수행 (비효율)
- 609개 row가 네트워크 전송 → 애플리케이션에서 1개로 그룹핑
---
multiset 방식 (cost=20.2 + 13.3 × filtered_actors)
Actor 필터링 먼저 → 각 Actor의 Film 서브쿼리
1. actor 테이블 스캔 (200 rows)
└─ LIKE '%LOLLOBRIGIDA%' → 1 row (필터링 후)
2. 필터링된 1개 actor에 대해 서브쿼리 실행:
- film_actor PRIMARY KEY 조회 (27.3 rows 추정)
- film PRIMARY KEY 조회 (27.3번)
- LIKE '%COMMANDMENTS EXPRESS%' → 1개 매칭
특징:
- Actor 조건을 먼저 적용하여 서브쿼리 실행 횟수 최소화
- 필터링된 1개 Actor만 네트워크 전송 (JSON 포함)
- Film 필터링은 각 actor 서브쿼리 내부에서 수행
---
실제 Total Cost 계산
fetchGroups
Total: 405
네트워크 전송: 609 rows (Actor + Film 중복 포함)
애플리케이션 처리: Map 생성 + Stream 변환
multiset
Total: 20.2 + (13.3 × 1) = 33.5
네트워크 전송: 1 row (Actor + JSON array)
애플리케이션 처리: JSON 역직렬화
결론: WHERE 조건이 있으면 multiset이 압도적으로 유리 (405 vs 33.5)
FetchGroups는 Actor를 나중에 필터링하고 multiset은 actor를 먼저 필터링해서 1개에 대한 film을 여러개 가져와서 현재 데이터에서는 더 유리한데 일반적인 사용법이 궁금합니다
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
JaeWon Kim님, Multiset을 사용하여 1:N 관계에서 데이터베이스 쿼리 성능을 향상시키고 결과를 DTO로 쉽게 매핑할 수 있는 방법에 대해 문의하신 점 잘 이해했습니다. Multiset 방식을 활용하면, 각 Actor에 대해 관련된 Film 정보를 서브쿼리를 통해 바로 가져올 수 있기 때문에, 특히 큰 데이터셋에서 성능 이점이 있을 수 있습니다.
Multiset 방식과 FetchGroups 방식을 비교하자면:
효율성: Multiset 방식은 Actor에 즉시 필터링을 적용하고, 관련된 데이터를 서브쿼리로 가져오기 때문에 필요한 데이터 양이 줄어듭니다. 반면, FetchGroups는 조인이 완료된 후에 필터링이 진행되어 필요 없는 데이터를 더 많이 전달하고 후처리합니다.
네트워크 전송량: Multiset 방식은 적은 양의 데이터를 네트워크를 통해 전송하므로 대용량 데이터 처리에 유리합니다. 특히, 네트워크 전송 비용이 높은 경우 명확한 이점이 있습니다.
코드 복잡성: Multiset 방식이 초기에는 다소 복잡하고 생소하게 느껴질 수 있지만, 익숙해지면 충분히 효율적인 코딩 패턴이 될 수 있습니다. 코드의 복잡성은 결국 개발자의 숙련도에 따라 다르게 느껴질 수 있습니다.
유연성: Multiset은 다양한 데이터 관계를 한 번의 쿼리로 쉽게 매핑할 수 있는 장점을 제공합니다. 특히 DTO로 직접 매핑하여 애플리케이션에서 추가 처리 없이 사용할 수 있습니다.
강의에 포함되지 않았던 이유는, 현실의 데이터베이스 스키마나 비즈니스 요구사항에 따라 모든 케이스에서 Multiset 방식이 더 나은 선택이 아닐 수도 있기 때문입니다. 특정 상황에서는 FetchGroups가 더 직관적이고 관리가 용이할 수 있습니다.
다음 링크에서 더 많은 정보를 참고하실 수 있습니다:
- jOOQ의 Multiset 사용법 공식 문서
- 병렬 처리와 네트워크 비용 분석에 관한 기초
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





