Java/JPA

Fetch Join(2) - xToOne과 xToMany의 차이

뽀루피 2024. 8. 27. 17:17

xToOne Fetch Join

우리가 기존에 알고있던 Fetch Join이다.

 

 

xToMany Fetch Join

xToOne 패치 조인과 다르게 부작용이 생긴다.

1. 페이징이 불가능하다. 만약 페이징을 설정하게 되면 모든 데이터를 DB에서 읽어오고 메모리에서 별도로 페이징을 해버린다. 이렇게되면 OutOfMemory 오류가 터질 수 있다. 위험하므로 사용하지 말아야한다. 페이징은 성능에 뛰어난 성능을 보이고 현업에서 많이 사용하므로 xToMany 관계에서는 패치 조인을 쓰면 안되겠다.

(페이징이 불가한 이유는 ToMany 관계는 조회 row 수를 늘리기 때문이다. 조회한 데이터에 같은 id의 데이터 수가 많으면 페이징하기 곤란하기 때문이다.)

 

2. 컬렉션 패치 조인은 1개만 사용할 수 있다. 2개 이상부터는 데이터가 부정합하게 조회될 수 있다.

 

 

 

 

그렇다면 페이징과 컬렉션 엔티티를 함께 조회하려면 어떻게 해야할까?

먼저, xToOne 관계는 전부 Fetch Join 을 해준다.

그 다음, 컬렉션은 지연로딩으로 조회하는데 성능 최적화를 위해 hibernate.default_batch_fetch_size 또는 @BatchSize를 적용한다. 

  • hibernate.default_batch_fetch_size: 글로벌 설정
  • @BatchSize: 개별 최적화

이 옵션을 사용하면 컬렉션이나, 프록시 객체를 한꺼번에 설정한 size 만큼 IN 쿼리로 조회한다.

아래는 batchSize를 돌렸을 때 DB에 전달되는 SQL문이다. 

    select
        oi1_0.order_id,
        oi1_0.order_item_id,
        oi1_0.count,
        oi1_0.item_id,
        oi1_0.order_price 
    from
        order_item oi1_0 
    where
        oi1_0.order_id in (1, 2, ?, ?, ...)

 

이런식으로 기존에 where order_id = 1 로 N번 쿼리를 호출했을 때에 비해 쿼리 호출 1번만에 조회할 수 있으므로 성능 최적화를 이룰 수 있다.

 

 

결론적으로 xToOne 관계는 패치 조인을 해도 페이징에 영향을 주지 않기 때문에 xToOne 관계는 패치 조인으로 쿼리 수를 줄이고, 나머지는 컬렉션이나 프록시 객체를 한꺼번에 불러올 수 있는 Batch Size 설정을 통해 최적화하자.

'Java > JPA' 카테고리의 다른 글

OSIV(OpenSessionInView)  (2) 2024.08.27
ddl-auto: create 적용 안되는 문제  (0) 2024.02.04