다대다 관계에서의 성능 ISSUE

황상익·2024년 10월 16일

다대다 관계에서의 성능 이슈

  1. 중간 테이블 처리 비용 증가
    두개의 엔티티 사이에 중간 테이블을 자동으로 생성해 관계를 관리
    중간 테이블에는 두 엔티티의 ID가 저장되어 있어 각 레코드 간의 메핑 관리
  • 읽기 작업 : 두개의 엔티티를 읽을 때 두번의 JOIN 필요
    각각의 엔티티와 중간 테이블을 조인한 후 중간 테이블 기준으로 다시 다른 엔티티와 조인하는 방식
    쿼리 복잡도 증가, 쿼리 실행 시간이 길어짐

  • 쓰기 작업 : 다대다 관계에서 새로운 관계를 추가하거나 삭제할때 중간테이블에 추가적인 insert, Delete 작업이 필요. 한 엔티티와 관련된 데이터를 삭제하면, 중간 테이블에서 해당 관계를 먼저 삭제한 후, 관련 엔티티에서 데이터를 삭제해야 합니다. 이로 인해 성능 저하

  1. N+1 문제
    Category가 여러 Book과 다대다 관계를 가지고 있다고 가정할 때, 하나의 Category를 조회할 때 Book 엔티티와의 다대다 관계를 지연 로딩으로 처리하면, 추가로 N개의 쿼리가 발생
    하나의 카테고리에 대해 모든 책을 가져올 때, 카테고리당 하나의 쿼리와 관련된 모든 책에 대해 N개의 쿼리가 추가적으로 실행

  2. 중복된 데이터 문제
    조인을 통해 데이터를 가져오는데, 결과적으로 동일한 엔티티 데이터가 여러 번 중복될 수 있습니다. 이는 메모리 사용량이 증가하게 되어 성능에 악영향

중간 테이블을 통한 다대다 풀기

중간 테이블(Join Table)을 명시적으로 사용하는 방식으로 다대다 관계를 풀어냅니다. 이 방식에서는 다대다 관계를 풀어서 일대다(OneToMany)와 다대일(ManyToOne) 관계로 변환하여 처리

두 엔티티가 서로 여러개의 인스턴스를 참조할 수 있기 때문에 이를 구현하기 위해서는 중간 테이블이 필요
양쪽 엔티티의 외래 키 포함 -> 두 엔티티 간의 연결을 관리

  • 중간 테이블을 중간 엔티티로 확장하여 메타데이터 관리 가능
    추가적인 정보를 저장 할 수 있다.

  • 추가적인 필드 저장:
    예를 들어, 책이 특정 서브 카테고리에 추가된 날짜나 상태 정보를 중간 엔티티에 저장할 수 있습니다.

  • 복잡한 비즈니스 로직 관리:
    중간 엔티티를 통해 두 엔티티 간의 상태나 연관된 비즈니스 로직을 관리할 수 있습니다.

  • 관계 속성 관리:
    예를 들어, 두 엔티티 간의 관계가 활성/비활성화 상태인지, 또는 이 관계가 언제 형성되었는지와 같은 정보도 중간 엔티티에 저장할 수 있습니다.

  1. 관계가 만들어진 날짜 추적
    addedDate 필드를 통해, 책이 특정 서브 카테고리에 언제 추가되었는지 추적할 수 있습니다. 이 정보는 도서 관리 시스템에서 중요한 메타데이터가 될 수 있습니다.
  2. 활성화 여부 관리
    isActive 필드를 통해, 이 책과 서브 카테고리 간의 관계가 현재 활성화된 상태인지, 비활성화된 상태인지 관리할 수 있습니다.
    예를 들어, 서브 카테고리에 더 이상 해당 책을 포함하고 싶지 않다면, isActive를 false로 설정할 수 있습니다.
  3. 중간 엔티티를 통한 추가 검색 및 필터링
    중간 엔티티에 추가된 필드를 통해 추가적인 검색 및 필터링 조건을 사용할 수 있습니다. 예를 들어, 특정 날짜 이후에 서브 카테고리에 추가된 책들만 검색하는 쿼리를 작성할 수 있습니다

장점: 성능을 최적화할 수 있으며, 중간 테이블에 추가적인 메타데이터(예: 생성 일자, 상태 정보)를 저장할 수 있습니다.

단점: 설계가 복잡해지고, 중간 엔티티를 직접 관리해야 하므로 구현 부담이 생길 수 있습니다

다대다 관계의 성능 문제 발생 시 해결 방법

  1. 지연 로딩(Lazy Loading) 사용
    다대다 관계에서 모든 데이터를 즉시 로딩하면 성능에 큰 영향을 미칠 수 있습니다. FetchType.LAZY를 사용하여 실제로 필요한 데이터만 로드

  2. 배치 쿼리 사용
    다대다 관계에서 N+1 문제를 해결하기 위해 배치(fetch join) 쿼리를 사용할 수 있습니다. Hibernate는 JOIN FETCH를 사용하여 관련 엔티티를 한 번에 로드

profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글