N+1
์ ์
N+1 ๋ฌธ์ ๋ [[entity]] ๊ฐ ๊ด๊ณ๋ฅผ ์กฐํํ ๋ ๋ฐ์ํ๋ ์ฑ๋ฅ ์ด์.
N๊ฐ์ ๋ถ๋ชจ [[entity]]๋ฅผ ์กฐํํ ํ(1๋ฒ์ ์ฟผ๋ฆฌ) ๊ฐ ๋ถ๋ชจ์ ์ฐ๊ด๋ ์์ ์ํฐํฐ๋ฅผ ์กฐํํ ๋ ์ถ๊ฐ์ ์ธ N๋ฒ์ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ ํ์
์์ธ
[[entity]] ๊ฐ ์ฐ๊ด ๊ด๊ณ
์ง์ฐ ๋ก๋ฉ(Lazy Loading)์ ๋์ ๋ฐฉ์
์ง์ฐ ๋ก๋ฉ์ ์ฐ๊ด ์ํฐํฐ๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ ๋๊น์ง ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ๋ฅผ ๋ฏธ๋ฃจ๋ ์ ๋ต
์ฐ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ์ค์ ๋ก ์ฌ์ฉํ๋ ์์ ์ ๊ฐ๊ฐ์ ์ํฐํฐ๋ง๋ค ๊ฐ๋ณ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๊ฒ๋จ
์์
์ผ๋๋ค(One-to-Many) ๊ด๊ณ
ํ๋์
Departemnt
์ ์ฌ๋ฌEmployee
๊ฐ ์ฐ๊ฒฐ๋๋ ๊ตฌ์กฐ (์ผ๋๋ค)
๋ค๋์ผ(Many-to-One) ๊ด๊ณ
์ฌ๋ฌ Member๊ฐ ํ๋์ ํ์ ์ฐ๊ฒฐ๋ ๊ด๊ณ (๋ค๋์ผ)
ํด๊ฒฐ ๋ฐฉ๋ฒ
ํ์น ์กฐ์ธ(Fetch Join) ์ฌ์ฉ
ํ ๋ฒ์ ์ฟผ๋ฆฌ๋ก ์ฐ๊ด๋ ์ํฐํฐ๊น์ง ํจ๊ป ์กฐํ
์ฃผ์ํ ์ 1 -> ๋ ์ฝ๋ ์ค๋ณต
member๊ฐ 3๊ฐ์ row๋ผ๋ฉด,
fetch join
๊ฒฐ๊ณผ 3๊ฐ์ row๊ฐ ์๋ต ๋ฐ๋๋ค.distinct
์ต์ ์ด ํ์ํ ์๋ ์์.
์ฃผ์ํ ์ 2 -> in-memory pagination
๋ ์ฝ๋ ์ค๋ณต์์ ํ์๋๋ ์ด์
member๊ฐ 3๊ฐ์ row๋ผ๋ฉด,
fetch join
๊ฒฐ๊ณผ 3๊ฐ์ row๊ฐ ์๋ต ๋ฐ๋๋ค.๋ฐ์ดํฐ๋ฒ ์ด์ค์์ pagination ํ๊ธฐ๋ ๋ถ๊ฐ๋ฅ.
๊ทธ๋ฌ๋ฏ๋ก ๋ชจ๋ record ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆฐ๋ค์์ ์ค๋ณต์ ์ ๊ฑฐํ๋ค์ ๊ทธ๋ฆฌ๊ณ pagination ์ ํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
fetch join์ ๊ทธ๋๋ก ์ฌ์ฉํ ๊บผ๋ผ๋ฉด..
์๋์ ๊ฐ์ด countQuery๋ฅผ ๋ณ๋๋ก ๋ถ๋ฆฌํ ํ์๊ฐ ์์๋ฏ.
์ ๋ฐ์ํ ๊น?
์นดํ ์์ ๊ณฑ(Cartesian Product) ๋ฌธ์
ํ ํ์ด 3๋ช ์ ๋ฉค๋ฒ์ 2๊ฐ์ ํ๋ก์ ํธ๋ฅผ ๊ฐ์ง๋ฉด ์ด 6๊ฐ์ row๊ฐ ์์ฑ
๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฌธ์
Hibernate๋ List ํ์ ์ ์ปฌ๋ ์ ์ Bag
Bag์ ์์๊ฐ ์๊ณ ์ค๋ณต์ ํ์ฉํ๋ ์๋ฃ๊ตฌ์กฐ
์ฌ๋ฌ ์ปฌ๋ ์ ์ ์กฐ์ธํ๋ฉด ๋ฐ์ดํฐ์ ์ ํ์ฑ์ ๋ณด์ฅ
์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?
Set ์ฌ์ฉ
๋ฐ์ดํฐ ์ ํฉ์ฑ ๋ฌธ์ ๋ ํ ์ ์๋ค.
์ฌ์ ํ ์ฌ๋ฌ ์ปฌ๋ ์ ์ Fetch Join์ ๊ถ์ฅ๋์ง ์์
๊ฐ๋ณ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ -
@BatchSize
๋ฅผ ์ฌ์ฉํด์ผํจ.
์ฃผ์ํ ์ 4 -> alias ์ด์
fetch join์ JPQL์ ๊ธฐ๋ฅ
JPA ํ์ค์์๋ ์ ์ฝ์ด ์๋ค.
Alias ์ฌ์ฉ ๋ถ๊ฐ
ON ์ ์ ์ด์ฉํ ํํฐ๋ง ๋ถ๊ฐ
๊ทธ๋ ์ง๋ง hibernate ์์๋ ์๋ ๊ธฐ๋ฅ์ ์ง์ํ๋ค.
findTeamsWithAgreementsBefore๋ฅผ ์ฌ์ฉํ ๋ ์๋์ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์.
agreements ์ปฌ๋ ์ ์๋ ํํฐ๋ง๋ ๋ฐ์ดํฐ๋ง ์กด์ฌ
์ค์ DB์๋ ๋ ๋ง์ Agreement๊ฐ ์์ ์ ์์
ํํฐ๋ง๋ ์ํ์์ ์ปฌ๋ ์ (agreements) ์ ์์ ํ๋ฉด
team.getAgreements().clear()
ํํฐ๋ง๋์ง ์์ Agreement๋ ์ญ์ ๋ ์ ์์
์ค๋ณตํค ์ด์
ํํฐ๋ง์ผ๋ก ์ธํด ๋ณด์ด์ง ์๋ Agreement๊ฐ ์๋ ์ํ์์
team.getAgreements().add(newAgreement)
์ด๋ฏธ ์กด์ฌํ๋ ID๋ฅผ ๊ฐ์ง Agreement๋ฅผ ์ถ๊ฐํ๋ ์๊ฐ์ค๋ณต ํค ์์ธ ๋ฐ์ํ๋ค.
๊ทธ๋ฌ๋ฏ๋ก..
join fetch์์ ํญ์ ์ฐ๊ด๋ ๋ชจ๋ ์ํฐํฐ๋ฅผ ๋ค ๋์ด์ค๋ ๊ฒ์ ๊ธฐ๋ณธ์ผ๋ก ํ๋ ๊ฒ์ด ์ข์๋ฏ
EntityGraph ์ฌ์ฉ
JPA๊ฐ ์ ๊ณตํ๋ ์ด๋ ธํ ์ด์ ์ผ๋ก, ํ์น ์กฐ์ธ๊ณผ ์ ์ฌํ ๊ธฐ๋ฅ
๋จ, Entity graph๋ left outer join์ผ๋ก๋ง ์ฟผ๋ฆฌ๊ฐ ๊ตฌ์ฑ๋จ.
@BatchSize ์ค์
์ง์ ๋ size๋งํผ IN ์ ๋ก ํ ๋ฒ์ ์กฐํ
hibernate.default_batch_fetch_size
๋ฅผ ํตํด ์ ์ญ ์ค์ ๋ ๊ฐ๋ฅ.
key์ ๊ฐ์๊ฐ 30๊ฐ์๊ณ BatchSize๋ก 20์ ์ง์ ํ๋ค๋ฉด,
select ~ from agreements where key in (?1, ?2, โฆ?20)
select ~ from agreements where key in (?1, ?2, โฆ?10)
๋ ๋ฒ์ ์ถ๊ฐ ์ฟผ๋ฆฌ๊ฐ ๋ฐํ๋๋ค.
์ฐ๊ด ๋ฐ์ดํฐ๊ฐ ๋์ฉ๋์ผ ๋, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ๊ณ ๋ คํ๋ฉด ๊ด์ฐฎ์ ์ ํ์ด ๋ ์ ์์๋ฏ
DTO ์ง์ ์กฐํ
ํ์ํ ๋ฐ์ดํฐ๋ง ์ง์ ์กฐํํ๋ ๋ฐฉ๋ฒ
Reference
https://medium.com/@liberatoreanita/analyze-and-understand-the-n-1-problem-in-hibernate-920cbc056705
https://www.baeldung.com/spring-hibernate-n1-problem
https://medium.com/@taesulee93/spring-data-jpa-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-n-1-query-problem-%EC%9D%98-%EB%8B%A4%EC%96%91%ED%95%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95%EA%B3%BC-%EC%9C%A0%EC%9A%A9%ED%95%9C-hibernate-%EC%84%A4%EC%A0%95-%EA%B0%92-3eadd956093e
Last updated
Was this helpful?