[하이버네이트 N+1 Select] Batch Patching으로 해결하기
간단하다. Member -> C 연관 관계 위에다가 @BatchSize라는 애노테이션을 붙여주면 된다. 애노테이션의 값으로는 해당 컬렉션 몇 개를 동시에 읽어올지 설정하면 된다.
[java]
...
@OneToMany(mappedBy = "owner")
@BatchSize(size=30)
private Set<Item> items;
...
[/java]
이렇게 설정해 두면 Member를 순회하면서 Item 컬렉션에 접근할 때 개별적으로 Item 컬렉션을 select 하는게 아니라 첫번째 Member의 Item 컬렉션에 접근할 때 미리 배치 사이즈 만큼의 컬렉션을 같이 가져오게 된다. 만약에 배치 사이즈를 30으로 했다면 n/30+1 로 문제 크기가 줄어든다. 실제로는 그렇게 간단한 로직은 아니였던 것 같은 기억이 난다. 하이버네이트 책에 보면 잘 설명되어 있지만 대충 저정도 쿼리가 발생하니까 그냥 저렇게 알고 있어도 될 것 같다.
이렇게 말이다. 테스트 데이타로 member 객체 100명을 만들어 놨으니 이전 같으면 100 + 1 = 101 번의 select 가 날아갔을 터인데.. 이번에는 4 + 1 번밖에 안날아 갔다.
하지만 이 방법은 필요없는 컬렉션까지도 미리 패치해오는 경우가 발생할 수 있으니 최선책은 아니라고 볼 수 있다. 물론 위와 같이 모든 Member 객체를 순회하며 모든 컬렉션에 접근하는 경우라면 이렇게 사용해도 괜찮겠지만 말이다... 그래서 이 방법 말고도 다른 해결책이 또 있다.
그건 다음에~