๐ฑ N+1 ๋ฌธ์ ๋?
JPA ์ฐ๊ด๊ด๊ณ์์ ์๊ธฐ๋ ์ด์๋ก ์ฐ๊ด ๊ด๊ณ๊ฐ ์ค์ ๋ ์ํฐํฐ๋ฅผ ์กฐํํ ๊ฒฝ์ฐ ์กฐํ๋ ๋ฐ์ดํฐ ๊ฐ์(N)๋งํผ ์ฐ๊ด ๊ด๊ณ์ ์กฐํ ์ฟผ๋ฆฌ๊ฐ ์ถ๊ฐ๋ก ๋ฐ์ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฌธ์ ๋ฅผ ๋งํ๋ค.
๐ค ๊ทธ๋ผ ์ด๋ป๊ฒ ํด๊ฒฐํด์ผ ํ ๊น?
1. Fetch Type์ Lazy๋ก ์ค์ ํ๋ค.
2. fetch join์ ์ฌ์ฉํ๋ค.
3. Batch Size๋ฅผ ์กฐ์ ํ๋ค.
์ฌ๊ธฐ์ ๋ 1, 2๋ฒ์ ๊ฐ์ง๊ณ ํด๊ฒฐํด ๋ณด์๋ค.
๐ฉ๐ป๐ป ํด๊ฒฐ ๊ณผ์ ๋ฐ ํ ์คํธ
๋๋ ์ด ํ๋ก์ ํธ์์ ๋ชจ๋ ์ ์ ๊ฐ์ฒด์ ๋ํด์ ๊ธ ์ ๋ณด์ ๊ฐ์ด ๋งคํํ๋ ์ฝ๋๋ฅผ ์์ฑํ์๋ค.
Member ๊ฐ์ฒด์์ fetch type์ Lazy๋ก ์ค์ ํ์๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ๋ง ๋ถ์ธ๋ค๊ณ ํด์ ํด๊ฒฐ์ด ๋์ง ์๋๋ค.
public ListResult<TestGetMembersResDto> testGetMembersV1() {
List<TestGetMembersResDto> testGetMembersResDtoList = new ArrayList<>();
List<Member> members = memberRepository.findAll();
for(Member member : members) {
TestGetMembersResDto testGetMembersResDto = TestGetMembersResDto.builder()
.memberId(member.getId())
.nickname(member.getNickname())
.imageUrl(member.getProfileImageUrl())
.postingCount((long)member.getPostings().size())
.build();
testGetMembersResDtoList.add(testGetMembersResDto);
}
return responseService.getListResult(testGetMembersResDtoList);
}
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋๋ค๊ณ ํด๋, ๋ฉค๋ฒ ๊ฐ์ฒด์์ ํฌ์คํ ๊ฐ์๋ฅผ ์ฐธ์กฐํด์ ๊ฐ์ ธ์ฌ ๋, ์ฌ์ ํ ํฌ์คํ ํ ์ด๋ธ์ ์กฐํํ๋ ์ฟผ๋ฆฌ๊ฐ ๋งค๋ฒ ๋๊ฐ๋ค. ์ฌ๊ธฐ์ ๊ฐ์ ธ์จ getReference๋ ๊ฐ์ง๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์ค์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด์๋ ์ฟผ๋ฆฌ๋ฅผ ์กฐํํ ์๋ฐ์ ์๋ ๊ฒ์ด๋ค!
๋ฐ๋ผ์ repository์์ ๊ฐ์ ๊ฐ์ ธ์ฌ ๋ fetch join์ ์ฌ์ฉํ์ฌ ํฌ์คํ ์ ์ค์ ์ ๋ณด๋ ํ ๋ฒ์ ๊ฐ์ ธ์ค๋๋ก ํ๋ค.
@Query("select m from Member m left join fetch m.postings")
List<Member> findAllFetch();
์ด๋ ๊ฒ ํ๋ฒ์ ๊ฐ์ ๊ฐ์ ธ์์ ๋๋ ์ฟผ๋ฆฌ๊ฐ ํ ๋ฒ๋ง ์คํ๋๋ ๊ฒ์ ํ์ธํด ๋ณผ ์ ์๋ค!
์ด๊ฑธ JMeter๋ฅผ ์ด์ฉํด์ ํ ์คํธํด๋ณด์!
๋ฐ์ดํฐ๋ฅผ ๋ช ๋ช ๋ง ๋ฃ๊ฒ ๋๋ค๋ฉด ํ ์คํธ ์ฐจ์ด๊ฐ ์ผ๋ง ๋์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํด์ 5000๋ช ์ ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ๊ณ ํ ์คํธํด๋ณด์๋ค.
์ด๋ ๊ฒ ํ์ ์ ๋ณด๋ฅผ ์์ฑํด ๋์๋ค.!
๐ซง fetch join์ ์ฌ์ฉํ๊ธฐ ์ ๊ณผ ํ
์ฝ 2.6๋ฐฐ ์ ๋ ๊ฐ์ ๋ ๊ฒ์ ํ์ธํด ๋ณผ ์ ์๋ค ใ ใ
ํฌ์คํธ๋งจ์ผ๋ก ํ์ธํ๋ฉด ์ฝ 3๋ฐฐ๊น์ง๋ ์ฐจ์ด๊ฐ ๋ฌ์๋ค. (709ms -> 237ms)
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Spring Cache์ ์ ์ฉํ ์กฐํ ์ฑ๋ฅ ๊ฐ์ (with. Redis) (0) | 2024.03.19 |
---|---|
[Spring] @PrePersist์ @PreUpdate (0) | 2024.03.16 |
[Spring] JWT AccessToken/RefreshToken ๊ตฌํ (with. Redis) (0) | 2024.03.12 |
[Spring] @AllArgsConstructor, @RequiredArgsConstructor ์ฌ์ฉ์ ์ง์ํ ์ด์ (0) | 2024.03.05 |
[Spring] @ExceptionHandler๋ฅผ ํตํ ์์ธ ์ฒ๋ฆฌ (+ DTO Validation) (0) | 2024.03.05 |