JPA 는 편리하지만 편리함 뒤에 숨어있는 성능 손실 위험이 있다. 이건 JPA가 그 자체로 성능 상 불리하다는 얘기가 아니라, 편하게만 쓰다보면 잘못 쓰는 길로 빠져서 성능에 해를 끼칠 위험도 꽤 있다는 얘기다.
여러가지 원칙이 있겠지만, 이번에 기억해둬야 할 원칙은 JPA는 필요한 것만 조회하자
엔티티
아래는 어떤 카테고리를 나타내는 엔티티다. 카테고리는 보통 하위에 동일한 타입의 다른 카테고리를 자식으로 가지고 있고, 상위에도 동일한 타입의 다른 카테고리를 부모로 가질 수 있다. parent_category_id 컬럼에는 인덱스가 걸려있고, 데이터는 약 54,000건 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
publicclassZZZCategoryextendsBaseEntityimplementsTreeEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
// ID를 인자로 받도록 변경 private Set<Long> getChildIds(Set<Long> ZZZCategoryIds){ Set<Long> ids = new HashSet<>(); if (ZZZCategoryIds == null) { return ids; }
ids.addAll(ZZZCategoryIds);
for (Long ZZZCategoryId : ZZZCategoryIds) { // ID 리스트를 반환하는 메서드로 대체 List<Long> childCategoryIds = ZZZCategoryRepository.findChildCategoryIds(ZZZCategoryId); ids.addAll(getChildIds(new HashSet<>(childCategoryIds))); }
return ids; }
엔티티를 통째로 가져오는 ZZZCategoryRepository.findAll(ZZZCategoryIds) 대신에 ID만 가져오는 메서드를 QueryDSL로 구현해서 대신 사용했다. 앞에서 얘기한 것처럼 parent_category_id에는 인덱스가 걸려 있으므로 조회 효율이 괜찮을 것이다.