one-to-may 의 관계에서 side effet 로 oom 의 발생가능성
254
작성한 질문수 1
안녕하세요 김영한 개발자님
수업을 듣던중 one-to-may 의 관계에서 side effet 로 oom 의 발생가능성에 대해 고민을 하게되어 질문드립니다.
테이블이 category - product - display_info 순으로 one-to-may 관계를 맺고있을 때, 만약
category 가 10개, product 테이블의 데이터의 갯수가 10만개, display_info 의 테이블의 데이터가 100 만개일때,
각각의 category 가 가지고있는 product 의 display_info 의 갯수를 확인하고 싶은 need 가 있으면,
아래와 같이 entity 의 메서드를 통해 받아올수 있다는것을 이해를 했습니다.
List<Category> categories = categoryRepository.findAll();
List<CategoryResult> categoryResults = categories
.stream()
.map(category -> {
//데이터 커지면 통계쿼리 처리가 좋을수도 있음.
List<Product> products = category.getProducts();
int count = products
.stream()
.map(product -> product.getDisplayInfos().size())
.reduce(0, Integer::sum);
return new CategoryResult(category.getId(), category.getName(), count);
})
.collect(Collectors.toList());
return categoryResults;
그런데 걱정이 되는것은 실제 데이터가 많으면 많아질수록 batch size 를 설정한다 하여도 가져올수 있는 양은 한정적이고
결국 categorise 의 products 에 쌓인 데이터들로 인해 oom 이 발생할것 같은데 어떻게 처리를 하면 되나요??
( 보통의 webpage 를 생각해보면 이렇게 많은 데이터를 가져올 일이없고 paging 을 이용할것 같긴 합니다. )
제가 생각하기에는 아래의 2가지 정도 해결책이 있어보입니다.
(1) one-to-many 의 관계를 사용하지 않고 명시적으로 fk 를 이용해서 repository 에서 find 를 호출 하는 방법.
을 사용해 봤는데 이방법은 batch size 셋팅을 한다하여도 당연하겠지만 in query 로 sql 이 호출되지 않았습니다.
당연히 속도도 현저히 늘려서 엄청난 시간이 걸렸습니다. ( 3분 -> 50분 )
( ps. 아래의 코드에서도 inquery 셋팅하는 방법이 있을까요? )
List<Category> categories = categoryRepository.findAll();
List<CategoryResult> categoryResults = categories.stream()
.map(category -> {
long categoryId = category.getId();
List<Product> products = productRepository.findAllByCategoryId(categoryId);
int count = products
.stream()
.map(product -> {
Long productId = product.getId();
List<DisplayInfo> displayInfos = displayInfoRepository.findAllByProductId(productId);
return displayInfos.size();
})
.reduce(0, Integer::sum);
return new CategoryResult(category.getId(), category.getName(), count);
})
.collect(Collectors.toList());
(2) count query 를 설정하는 방법
위의 needs 의 경우 통계쿼리처리를 하면 되겠지만, 만약 통계 쿼리로 처리하지못하는 로직이 있으면 어떻게 처리를 할수있을까요?
마지막 질문으로 위와 같이 oom 의 위험에도 불구하고 one-to-many 관계를 써야하나요??
서비스에서의 가장큰 위험은 예상되지않은 에러라고 생각이 되는데 이경우 어떤 테이블이 어떻게 데이터가 많아질지 모르는 상황에서 위의 상황이 발생할수 있다고 생각이 됩니다.
그럼에도 불구하고 성능적인 측면에서 one-to-many 를 쓰지않으면 성능이 너무나도 좋지않아서 고민입니다.
긴글 읽어주셔서 감사합니다.
답변 1
0
안녕하세요. 오지훈님 좋은 질문입니다
결론을 말씀드리면 이렇게 데이터가 많은 경우에는 OneToMany 관계를 사용하는 것이 적절하지 않습니다.
특히 문제가 되는 부분이 category - product 관계인데요.
실무에서는 Product -> Category로 ManyToOne 관계만 있어도 충분히 문제를 잘 해결할 수 있습니다.
쿼리를 실행할 때도 특정 카테고리에 속한 Product 목록을 찾고 싶으면 다음과 같이 쿼리하면 됩니다.
select p from Product p where p.category = :category
감사합니다.
강의 관련 외 질문입니다.
0
68
2
SpringBoot4 + Hibernate7 모듈 등록 방법 공유
0
92
1
BeanCreationException
0
91
3
Update 후 UpdateMemberResponse 매핑할 때
0
50
1
트랜잭션을 사용 안 할 때 커넥션은 언제 가져오나요?
0
101
2
페이징 + 검색조건 관련해서 질문드립니다.
0
70
1
Query Dsl Q파일 질문입니다.
0
84
1
루트 쿼리라는것은
0
60
1
메서드를 분리하는 기준
0
65
1
findAllWithMemberDelivery 메서드 질문드립니다.
0
111
3
연관관계 매핑을 안 쓸 경우, 사용해야 하는 전략
0
86
2
fetch join과 영속화와 OSIV의 관계
0
87
2
Distinct 사용 전 결과에 대한 의문
0
117
2
레포지토리 계층에서의 트랜잭션에 대한 의문
0
59
1
영속성 컨텍스트 생명주기의 신기한 부분이 있습니다.
0
78
2
dto 필드 속 엔티티 여부
0
60
1
뷰템플릿 사용 시
0
77
2
Result 클래스 관련 질문
0
56
1
@PostConstruct 프록시 관련 질문드립니다
0
86
1
DTO 대신 Form 사용은 안되나요?
0
138
1
OSIV ON 상태일 때
0
96
1
fetch join VS fetch join 페이징 궁금증
0
187
2
양방향 연관관계 알아보는 법?
0
106
1
16강 17강 간단 정리 이게 맞을까요 ?
0
166
2





