Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pet 도메인 지연 로딩 설정 및 N+1 문제 해결 #586

Open
J-I-H-O opened this issue Sep 24, 2024 · 1 comment · May be fixed by #606
Open

pet 도메인 지연 로딩 설정 및 N+1 문제 해결 #586

J-I-H-O opened this issue Sep 24, 2024 · 1 comment · May be fixed by #606
Assignees
Labels
Milestone

Comments

@J-I-H-O
Copy link
Contributor

J-I-H-O commented Sep 24, 2024

요구 사항

  • member fetch 전략 LAZY로 수정
  • memberId로 조회 시 N+1 문제가 발생하는 현상 수정
@takoyakimchi takoyakimchi added the 🖥 backend backend label Oct 2, 2024
@J-I-H-O J-I-H-O self-assigned this Oct 2, 2024
@J-I-H-O J-I-H-O added this to the Sprint6 milestone Oct 2, 2024
@J-I-H-O
Copy link
Contributor Author

J-I-H-O commented Oct 2, 2024

1. as-is

1.1. findById()

Pet 도메인은 Member와 ManyToOne 관계, 기존에는 fetch 전략이 Eager로 설정되어 있었음.
ManyToOne관계이고 Eager로 설정되어 있기 때문에 id로 Pet 조회(findById) 시 아래와 같이 Join해서 한번에 조회해옴

Hibernate: 
    select
        p1_0.id,
        p1_0.birth_date,
        p1_0.description,
        p1_0.gender,
        p1_0.image_url,
        p1_0.member_id,
        m1_0.id,
        m1_0.image_url,
        m1_0.name,
        m1_0.tag,
        p1_0.name,
        p1_0.size_type 
    from
        pet p1_0 
    join
        member m1_0 
            on m1_0.id=p1_0.member_id 
    where
        p1_0.id=?

1.2. findByMemberId()
이때 memberId로 pet을 조회하려 하면 N+1 문제 발생

  • 즉시 로딩으로 설정했기 때문에 알아서 join해서 조회할 것이라고 기대했지만, spring data JPA의 query creation 기능을 사용하면 내부적으로 JPQL을 사용하기 때문에 join하지 않음
  • JPQL은 로딩 전략을 고려하지 않고 쿼리를 만들기 때문에 발생한 일
Hibernate: 
    select
        p1_0.id,
        p1_0.birth_date,
        p1_0.description,
        p1_0.gender,
        p1_0.image_url,
        p1_0.member_id,
        p1_0.name,
        p1_0.size_type 
    from
        pet p1_0 
    where
        p1_0.member_id=?

Hibernate: # N+1
    select
        m1_0.id,
        m1_0.image_url,
        m1_0.name,
        m1_0.tag 
    from
        member m1_0 
    where
        m1_0.id=?

2. to-be

  • 로딩 전략을 컨벤션에 맞춰 Lazy로 설정
@Entity
public class Pet {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false)
    private Member member;
}
  • 로딩 전략 변경에 따른 N+1 문제 해결을 위해 Member 엔티티와 fetch join 하도록 변경

1.1. findById()

@Query("""
        SELECT p
        FROM Pet p
        JOIN FETCH p.member m
        WHERE p.id = :id
        """)
Optional<Pet> findById(Long id);
    select
        p1_0.id,
        p1_0.birth_date,
        p1_0.description,
        p1_0.gender,
        p1_0.image_url,
        p1_0.member_id,
        m1_0.id,
        m1_0.image_url,
        m1_0.name,
        m1_0.tag,
        p1_0.name,
        p1_0.size_type 
    from
        pet p1_0 
    join
        member m1_0 
            on m1_0.id=p1_0.member_id 
    where
        p1_0.id=?

1.2. findByMemberId()

@Query("""
        SELECT p
        FROM Pet p
        JOIN FETCH p.member m
        WHERE m.id = :memberId
        """)
List<Pet> findByMemberId(Long memberId);
    select
        p1_0.id,
        p1_0.birth_date,
        p1_0.description,
        p1_0.gender,
        p1_0.image_url,
        p1_0.member_id,
        m1_0.id,
        m1_0.image_url,
        m1_0.name,
        m1_0.tag,
        p1_0.name,
        p1_0.size_type 
    from
        pet p1_0 
    join
        member m1_0 
            on m1_0.id=p1_0.member_id 
    where
        p1_0.member_id=?

@J-I-H-O J-I-H-O changed the title pet 도메인 수정 pet 도메인 지연 로딩 설정 및 N+1 문제 해결 Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: No status
2 participants