kwonslog / how-to-use-jpa

0 stars 0 forks source link

7회 - 성능 #18

Open kwonslog opened 4 weeks ago

kwonslog commented 4 weeks ago

즉시 로딩과 지연 로딩

성능을 최적화 하기 위해 기본 패치 전략은 지연 로딩 방식을 사용한다. 그 이유는 컬렉션 데이터를 가져오는 타이밍을 늦추게 만들어서 조회 속도나 메모리를 효율적으로 사용하기 위함이다.

그럼 즉시 로딩은 언제 사용해야 할까? 단순하게 생각하면 데이터가 단건이거나 연관된 엔티티들이 많지 않은 경우이다. 지연 로딩 방식과 비교해서 생각해 보자.

지연 로딩

일반적으로 다대일 관계에서 에 해당하는 컬렉션 데이터에 사용한다. 하나의 엔티티가 다수의 엔티티와 연관관계가 있을때 즉시 로딩은 한번에 조회되는 데이터의 크기가 문제 될 수 있다. 또한 조회 된 결과를 사용하지 않을 수도 있다. 그래서 지연 로딩을 적용하여 실제 값을 사용하는 시점에 데이터를 조회하도록 한다.

N + 1 문제

지연 로딩은 실제 값을 사용하는 시점에 추가 쿼리가 발생한다. 만약 컬렉션 데이터를 순환하며 모든 데이터에 접근한다면 성능이 저하 될 수 있다. 해결 방법은 패치 조인, 배치사이즈, 엔티티 그래프를 사용하는 방법이 있다.

2차 캐시

EntityManager 는 영속성 컨텍스트를 관리하며 이것을 1차 캐시라고 할 수 있다. 1차 캐시에 저장된(영속화) 엔티티는 해당 컨텍스트 안에서만 사용 된다.

2차 캐시는 EntityManager 간에 공유해서 사용하는 방식이다. 기본적으로 2차 캐시는 비활성화 되어 있어 명시적으로 Ehcache, Redis 등 외부 provider 를 설정하고 엔티티 클래스에 @Cacheable 을 사용하여 활성화 한다.

처리 순서

엔티티를 저장하는 경우

  1. 1차 캐시
  2. 데이터베이스
  3. 2차 캐시

엔티티를 조회하는 경우

  1. 1차 캐시
  2. 2차 캐시
  3. 데이터베이스

캐시 관리

2차 캐싱을 처리 하는 방법은 자동과 수동 모두 가능하다. 자동으로 하는 경우 @Cache 로 캐시 전략을 설정 하면 된다.

캐시 전략의 종류는 READ_WRITE, READ_ONLY, NONSTRICT_READ_WRITE,TRANSACTIONAL

수동으로 하는 경우 entityManager.getEntityManagerFactory() 를 통해 접근하여 처리 할 수 있다.

캐시 데이터의 제한값을 설정이 필요하고 제한값에 도달한 이후 데이터를 어떻게 관리 할 것인지 설정이 필요하다. LRU는 가장 오랫동안 사용되지 않는 값을 무효화 한다. LFU는 가장 사용량이 적은 값을 무효화 한다.

kwonslog commented 4 weeks ago

성능 최적화

참고자료 요약

연관되어 있는 엔티티가 ToOne 인 경우 패치 조인을 사용하여 한번에 가져온다.

연관되어 있는 엔티티가 ToMany 인 경우

kwonslog commented 4 weeks ago

JPA 실무 19가지 팁

https://velog.io/@wisepine/JPA-%EC%82%AC%EC%9A%A9-%EC%8B%9C-19%EA%B0%80%EC%A7%80-Tip

kwonslog commented 3 weeks ago

배치 처리

jpa를 이용한 batch insert 와 jdbc 를 이용한 방법 중에서 성능은 jdbc를 사용하는 것이 더 좋다. 성능비교1,성능비교2

jpa는 영속성 관리를 통해 실제 쿼리가 발생하기 때문에 단순히 대량의 데이터를 insert 할때는 불리한 점이 있다.

jpa에서 @Id 생성 전략이 IDENTITY이면 batch insert 를 사용 할 수 없다. 결국 돌고 돌아 JdbcTemplate 를 사용하게 된다.관련링크

jpa에서 batch insert 하기 위해 설정해야 하는 부분들이 있다. 그 중 batchSize 값을 지정해야 한다.flush, clear 처리를 통해 쿼리를 실행하는데 batchSize 만큼 처리하기 때문이다.관련링크

정리

대량의 데이터를 빠르게 insert 해야 한다면 JdbcTemplate을 사용하자.