작성
·
394
1
안녕하세요. batch size에 관해서 질문드립니다.
예를들어, 강의처럼 member와 order엔티티로 하겠습니다. (연간관계는 일대다)
batchsize=3인 상태이구용
member.orders는 lazy상태이고, db에는 member1~6까지 6개가 들어있다고 가정하겠습니다. (기본키id도 1~6)
jpql: select m from Member m 의 결과로는
List<Member> results 이고, size = 6인객체가 오겠네요
results.foreach(m -> m.getOrders().size)) 이런식으로 results를 전체순환하면서 사용하는게 아닌 아래처럼 사용하면
results.get(3).getOrders().size()
results.get(5).getOrders().size()
in절에는 get3과 5에 해당하는 외래키 id가 4, 6 두개가 나갈것으로 예상했는데, 쿼리를 보니 4, 5, 6 이렇게 나가더라구요.
results.get(3).getOrders().size() 이렇게만 해도 in절에 4 하나만 나가는게 아니라 위와 동일하게 4, 5, 6 으로 되고..
results.get(0).getOrders().size()으로 하게 되면 1,2,3 으로,
results.get(5).getOrders().size()으로 하게되면 6,5,4로 되더라구요.
그래서 일단 "초기화 안된 콜렉션 타입의 proxy를 실제 db에서 조회하려고 할때는, 무조건 batchsize에 설정된 사이즈만큼 동시에 읽어오고, 엔티티화해서 영속성컨텍스트에 미리 올려놓는다" 라고 생각하려 합니당
제가 궁금한 점은 in절로 내보내야할 id들을 가져오는 과정입니다.
orders는 member의 콜렉션 프록시 이므로(=orders테이블에 memberid가 외래키)
영속성컨텍스트에 이미 로딩되어있는 member엔티티들의 키를 대상으로 in절로 내보낼 id들을 찾아온다 라고 생각하면 맞을까요?
제일 의문이었던게 results.get(5).getOrders().size()를 했을때 in절에 6,7,8이 아니라 자동으로 6,5,4로 되는것이 궁금했습니다. 어떻게 6번이 마지막인지 알고 범위내의 in절을 생성하는지..
em.detach(members.get(1)) 을 한 상태에서
results.get(0).getOrders().size() 하게 되면 1,3,4 로 나가는것을 보아 영속성 컨텍스트에 존재하는 엔티티를 참조하는게 맞는것 같다는 생각인데 확실치 않아서 문의드립니다.
(더 정확히는, 영속성 컨텍스트에 있으면서 proxy가 초기화 되지 않은 상태인 것들을 대상으로 in절에 보낼 id생성인듯 합니다
시나리오 ->
results.get(0).getOrders().size()를 할 경우
)
감사합니다!
답변 1
2
안녕하세요. 이용조님
생각하신 내용들이 대부분 맞을꺼에요. 추가로 하이버네이트가 내부에서 다양하게 계산하고 최적화 하는 알고리즘들이 들어갑니다. (다음을 참고해주세요)
https://www.inflearn.com/questions/34469
감사합니다.