김영환님의 강의 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화 보면서 공부한 내용입니다.
📝 특징
페이징이 불가능
하다💡 해결법
ToOne
관계는 페치 조인한다- 컬렉션은 지연로딩으로 조회한다
- 지연 로딩 성능 최적화를 위해
hibernate.default_batch_fetch_size
,@BatchSize
를 적용한다
→ hibernate.default_batch_fetch_size : 글로벌 설정 (적어온 갯수만큼 미리 땡겨옴)
→ @BatchSize : 개별 최적화
→ 이 옵션을 사용하면 컬렉션이나 프록시 객체를 한꺼번에 설정한 size만큼 IN 쿼리로 조회한다
/* 방법 1 */
// application.yml
default_batch_fetch_size: 100 # IN 조건 추가해서 한 번에 100개 조회가능
// 사이즈 중요!
// 사이즈는 100 ~ 1000 사이를 선택하는 것을 권장
/* 방법 2 */
// Order.java
@BatchSize(size=1000) // 컬렉션인 경우
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
// Item.java
@BatchSize(size = 1000) // 컬렉션이 아닌 경우
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {
✅ 쿼리 호출 수가 1+N
에서 1+1
으로 최적화 된다
✅ 조인보다 DB 데이터 전송량이 최적화 된다
✅ 페이징 처리가 가능하다
📝 특징
private List<OrderItemQueryDto> findOrderItems(Long orderId) {
return em.createQuery(
"select new jpabook.jpashop.repository.order.query.OrderItemQueryDto(oi.order.id, i.name, oi.orderPrice, oi.count)" +
" from OrderItem oi" +
" join oi.item i" +
" where oi.order.id = :orderId", // OrderItem에서 item은 "ToOne" 관계이므로 join 으로 처리함OrderItemQueryDto.class)
.setParameter("orderId", orderId)
.getResultList();
}
📝 문제점
📝 특징
OrderItem
을 한꺼번에 조회 public List<OrderQueryDto> findAllByDto_optimization() {
List<OrderQueryDto> result = findOrders();
List<Long> orderIds = toOrderIds(result);
Map<Long, List<OrderItemQueryDto>> orderItemMap = findOrderItemMap(orderIds);
result.forEach(o -> o.setOrderItems(orderItemMap.get(o.getOrderId())));
return result;
}
📝 특징
📝 단점
public List<OrderFlatDto> findAllByDto_flat() {
return em.createQuery(
"select new "
+ "jpabook.jpashop.repository.order.query.OrderFlatDto(o.id, m.name, o.orderDate, o.status, d.address, i.name, oi.orderPrice, oi.count)"
+ " from Order o"
+ " join o.member m"
+ " join o.delivery d"
+ " join o.orderItems oi"
+ " join oi.item i", OrderFlatDto.class)
.getResultList();
}
📝 권장순서
hibernate.default_batch_fetch_size
, @BatchSize
로 최적화💡
엔티티 조회 방식은 JPA가 많은 부분을 최적화 해주기 때문에 단순한 코드를 유지하면서 성능을 최적화할 수 있다
반면에 DTO 조회 방식은 SQL을 직접 다루는 것과 유사하기 때문에 둘 사이에 줄타기를 해야한다
📝 OSIV
📝 OSIV ON
✅ OSIV ON의 장점
✅ OSIV ON의 단점
📝 OSIV OFF
✅ OSIV OFF의 장점
✅ OSIV OFF의 단점