강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của rladnjs7055010
rladnjs7055010

câu hỏi đã được viết

JOOQ ngoài đời thực! Gõ SQL an toàn với Java

Tạo điều kiện tìm kiếm đơn giản bằng Điều kiện

안녕하세요 FetchGroups에서 Multiset방식 사용하면 어떤가 해서 물어봅니다

Viết

·

53

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을 여러개 가져와서 현재 데이터에서는 더 유리한데 일반적인 사용법이 궁금합니다

javasqlspring-bootjooqdsl

Câu trả lời 1

0

안녕하세요, 인프런 AI 인턴입니다.

JaeWon Kim님, Multiset을 사용하여 1:N 관계에서 데이터베이스 쿼리 성능을 향상시키고 결과를 DTO로 쉽게 매핑할 수 있는 방법에 대해 문의하신 점 잘 이해했습니다. Multiset 방식을 활용하면, 각 Actor에 대해 관련된 Film 정보를 서브쿼리를 통해 바로 가져올 수 있기 때문에, 특히 큰 데이터셋에서 성능 이점이 있을 수 있습니다.

Multiset 방식과 FetchGroups 방식을 비교하자면:

  1. 효율성: Multiset 방식은 Actor에 즉시 필터링을 적용하고, 관련된 데이터를 서브쿼리로 가져오기 때문에 필요한 데이터 양이 줄어듭니다. 반면, FetchGroups는 조인이 완료된 후에 필터링이 진행되어 필요 없는 데이터를 더 많이 전달하고 후처리합니다.

  2. 네트워크 전송량: Multiset 방식은 적은 양의 데이터를 네트워크를 통해 전송하므로 대용량 데이터 처리에 유리합니다. 특히, 네트워크 전송 비용이 높은 경우 명확한 이점이 있습니다.

  3. 코드 복잡성: Multiset 방식이 초기에는 다소 복잡하고 생소하게 느껴질 수 있지만, 익숙해지면 충분히 효율적인 코딩 패턴이 될 수 있습니다. 코드의 복잡성은 결국 개발자의 숙련도에 따라 다르게 느껴질 수 있습니다.

  4. 유연성: Multiset은 다양한 데이터 관계를 한 번의 쿼리로 쉽게 매핑할 수 있는 장점을 제공합니다. 특히 DTO로 직접 매핑하여 애플리케이션에서 추가 처리 없이 사용할 수 있습니다.

강의에 포함되지 않았던 이유는, 현실의 데이터베이스 스키마나 비즈니스 요구사항에 따라 모든 케이스에서 Multiset 방식이 더 나은 선택이 아닐 수도 있기 때문입니다. 특정 상황에서는 FetchGroups가 더 직관적이고 관리가 용이할 수 있습니다.

다음 링크에서 더 많은 정보를 참고하실 수 있습니다:
- jOOQ의 Multiset 사용법 공식 문서
- 병렬 처리와 네트워크 비용 분석에 관한 기초

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Hình ảnh hồ sơ của rladnjs7055010
rladnjs7055010

câu hỏi đã được viết

Đặt câu hỏi