수십억건에서 QUERYDSL 사용하기

Y39·2023년 4월 3일
0

toBeProgrammer

목록 보기
81/88

1. 수천만에서 수억개의 데이터 어떻게 처리하나?

1. extends/ implemnet 사용하지 않기

  • JpaRepository 사용하지 않음 → 불편해
  • entity 지정도 번거로움
  • 자유롭게 Querydsl를 사용할 방법 찾기
  • 결론: queryFactory만을 이용해서 Querydsl만 사용할 수 있도록 만든다.

2. 동적쿼리 사용하기

  • if문을 이용하면 복잡해지고 가독성이 떨어짐
  • BooleanExpression을 통해서 자동으로 조건절에서 제거

2. 성능개선- select

1. exist 메소드 금지

  • count(1)>0으로 대체
    • 발견하는 순간 끝나기 때문에 성능차이가 크다.
  • limit 1로 조회를 제한
    • 특이사항: null이냐 아니냐고 결과값이 나옴

2. Cross Join 회피

  • cross join은 모든 가능성에 대한 것이여서 성능 저하가 생김
  • 묵시적 join으로 cross join이 발생할 수 있음
    • 최적화를 직접할 수 있다면 db에게 맡길필요 없다.
    • Hibernate 이슈
  • 해결: 명시적 join으로 cross를 막는다.

3. Entity보다 DTO를 우선으로 사용

  • Entity 사용시 문제
    • n+1 문제
    • 불필요한 컬럼들도 조회됨
    • 단순 조회 기능에서 성능 이슈 요소가 발생됨
  • Entity 조회와 Dto 조회를 구분
    • 고강도 성능 개선, 대량의 데이터 조회의 경우 Dto 사용
  • 조회 컬럼을 최소화
    • 이미 매개변수로 온 데이터는 as 표현식으로 대체함
  • select 컬럼에 entity 자제
    • oneToone은 lazy loading이 안된다. ⇒ 매건 마다 조회

3. Group By 최적화

  • filesort가 반드시 작동해서 성능저하로 이어진다.
  • sql에선 orderByNull로 넘어갈 수 있음
  • JPA에서는 orderByNull이 없기 때문에 직접 구현해서 넣어준다.
  • 정렬이 필요하더라도 조회결과가 100건 이하면, 애플리케이션에서 정렬해라
    • 단, 페이징일 경우는 orderByNull 못쓴다.
    • DB서버 보다는 WAS 서버가 훨씬 널널하기 때문에 자잘한건 애플리케이션에서 처리해도 좋음

4. 커버링 인덱스

: 쿼리 충족을 위한 모든 컬럼을 갖고 있는 인텍스

  • select, where, order by, group by 등에서 사용되는 모든 컬럼이 인덱스에 포함됨
  • 페이징 성능을 향상시키는 보편적인 방법
  • 하지만, JPQL from 절의 서브쿼리 지원을 안 함
  • JPQL에서의 우회법
    • Cluster Key(PK)를 커버링 인덱스로 조회 → 조회된 key로 select 컬럼 후속 조회

3. Update 성능 향상

1. 일괄 Update 사용으로 최적화

  • 직접 가져와서 하나씩 update하면 성능 저하가 커진다.
    • 무분별한 dirty checking이 생김
  • 단점: hibernate 캐시는 일괄 업데이트 시에 업데이트가 안됨
    • Dirty checkong: 실시간 비즈니스에 좋음
    • Querydsl.update: 대량의 업데이트

결론: Entity와 DTO의 분리는 진짜 중요. (필요한 항목만 조회, 업데이트)

4. JPA Bulk Insert 자제

JPA에서는 JDB의 Insert 합치기 옵션이 적용되지 않는다.

  • merge, persist 보다 batch 훨씬 성능이 좋다.
  • jdbcTemplate로 처리 가능하지만, Type Safe가 어려움
profile
System.out.print("Bold")

0개의 댓글