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

[Feature] - default_batch_fetch_size 적용 #647

Merged
merged 2 commits into from
Jan 19, 2025
Merged

Conversation

Libienz
Copy link
Contributor

@Libienz Libienz commented Jan 18, 2025

✅ 작업 내용

  • default_batch_fetch_size를 100으로 설정

🙈 참고 사항

현재 JPA 연관관계로 인해 데이터를 가져올 때 SELECT한 row 수 만큼 추가 쿼리가 발생하는 N+1문제가 발생합니다.
연관된 객체를 가져올 때 batch_size만큼 가져오도록 설정하여 N+1문제를 완화할 수 있습니다.
default_batch_fetch_size를 적용하여 한번에 100개씩 IN절을 활용하여 가져오도록 최적화 되었습니다.

성능 측정

26.83프로 성능 개선 달성

Jmeter 테스트 시나리오

  • 조회 대상 여행기: 2박 3일 여행기 (각 날짜는 3개의 장소 지정)
  • thread: 100
  • duration: 120sec

batch_fetch_size 미지정

image

  • avg: 41

batch_fetch_size 100 설정

image

  • avg: 30
발생 쿼리 비교

발생 쿼리 비교

batch_fetch_size 미지정

Hibernate: 
    select
        t1_0.id,
        t1_0.author_id,
        t1_0.created_at,
        t1_0.deleted_at,
        t1_0.like_count,
        t1_0.modified_at,
        t1_0.thumbnail,
        t1_0.title 
    from
        travelogue t1_0 
    where
        t1_0.id=? 
        and (
            t1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tt1_0.id,
        tt1_0.tag_id,
        tt1_0.travelogue_id 
    from
        travelogue_tag tt1_0 
    where
        tt1_0.travelogue_id=?
Hibernate: 
    select
        m1_0.id,
        m1_0.created_at,
        m1_0.deleted_at,
        m1_0.email,
        m1_0.kakao_id,
        m1_0.login_type,
        m1_0.modified_at,
        m1_0.nickname,
        m1_0.password,
        m1_0.profile_image_url 
    from
        member m1_0 
    where
        m1_0.id=?
Hibernate: 
    select
        td1_0.travelogue_id,
        td1_0.id,
        td1_0.created_at,
        td1_0.deleted_at,
        td1_0.modified_at,
        td1_0.day_order 
    from
        travelogue_day td1_0 
    where
        td1_0.travelogue_id=? 
        and (
            td1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_day_id,
        tp1_0.id,
        tp1_0.country_code,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.description,
        tp1_0.modified_at,
        tp1_0.name,
        tp1_0.place_order,
        tp1_0.place_id,
        tp1_0.latitude,
        tp1_0.longitude 
    from
        travelogue_place tp1_0 
    where
        tp1_0.travelogue_day_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_day_id,
        tp1_0.id,
        tp1_0.country_code,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.description,
        tp1_0.modified_at,
        tp1_0.name,
        tp1_0.place_order,
        tp1_0.place_id,
        tp1_0.latitude,
        tp1_0.longitude 
    from
        travelogue_place tp1_0 
    where
        tp1_0.travelogue_day_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_day_id,
        tp1_0.id,
        tp1_0.country_code,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.description,
        tp1_0.modified_at,
        tp1_0.name,
        tp1_0.place_order,
        tp1_0.place_id,
        tp1_0.latitude,
        tp1_0.longitude 
    from
        travelogue_place tp1_0 
    where
        tp1_0.travelogue_day_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id=? 
        and (
            tp1_0.deleted_at IS NULL
        )

batch_fetch_size 지정

Hibernate: 
    select
        t1_0.id,
        t1_0.author_id,
        t1_0.created_at,
        t1_0.deleted_at,
        t1_0.like_count,
        t1_0.modified_at,
        t1_0.thumbnail,
        t1_0.title 
    from
        travelogue t1_0 
    where
        t1_0.id=? 
        and (
            t1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tt1_0.id,
        tt1_0.tag_id,
        tt1_0.travelogue_id 
    from
        travelogue_tag tt1_0 
    where
        tt1_0.travelogue_id=?
Hibernate: 
    select
        m1_0.id,
        m1_0.created_at,
        m1_0.deleted_at,
        m1_0.email,
        m1_0.kakao_id,
        m1_0.login_type,
        m1_0.modified_at,
        m1_0.nickname,
        m1_0.password,
        m1_0.profile_image_url 
    from
        member m1_0 
    where
        m1_0.id=?
Hibernate: 
    select
        td1_0.travelogue_id,
        td1_0.id,
        td1_0.created_at,
        td1_0.deleted_at,
        td1_0.modified_at,
        td1_0.day_order 
    from
        travelogue_day td1_0 
    where
        td1_0.travelogue_id=? 
        and (
            td1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_day_id,
        tp1_0.id,
        tp1_0.country_code,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.description,
        tp1_0.modified_at,
        tp1_0.name,
        tp1_0.place_order,
        tp1_0.place_id,
        tp1_0.latitude,
        tp1_0.longitude 
    from
        travelogue_place tp1_0 
    where
        tp1_0.travelogue_day_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
        and (
            tp1_0.deleted_at IS NULL
        )
Hibernate: 
    select
        tp1_0.travelogue_place_id,
        tp1_0.id,
        tp1_0.created_at,
        tp1_0.deleted_at,
        tp1_0.photo_key,
        tp1_0.modified_at,
        tp1_0.photo_order 
    from
        travelogue_photo tp1_0 
    where
        tp1_0.travelogue_place_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
        and (
            tp1_0.deleted_at IS NULL
        )

@Libienz Libienz self-assigned this Jan 18, 2025
@Libienz Libienz changed the title Feature/be/#646 [Feature] - default_batch_fetch_size 적용 Jan 18, 2025
@Libienz Libienz linked an issue Jan 18, 2025 that may be closed by this pull request
1 task
Copy link

Test Results

 31 files   31 suites   57s ⏱️
312 tests 311 ✅ 1 💤 0 ❌
324 runs  323 ✅ 1 💤 0 ❌

Results for commit 35c7b73.

@Libienz Libienz requested review from eunjungL, slimsha2dy, nak-honest and hangillee and removed request for eunjungL and slimsha2dy January 18, 2025 18:19
Copy link
Contributor

@eunjungL eunjungL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트와 일반 application.yml 파일에 배치 사이즈 적용한 거 확인했습니다~
수고하셨습니다 리비!

@Libienz Libienz merged commit 0192d2f into develop/be Jan 19, 2025
3 checks passed
@Libienz Libienz deleted the feature/be/#646 branch January 19, 2025 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[Feature] - default_batch_fetch_size 적용
2 participants