[JPA] 읽기 전용 쿼리 최적화(미완성)

  1. 스칼라 타입으로 조회
    • 엔티티로 조회 대신 스칼라 타입 ( 기본 데이터 타입 ) 으로 필드 조회
    • 영속성 컨텍스트가 결과 관리 X 메모리 사용을 줄일 수 있다.
    select o.id, o.name, o.price from Order o
  1. 읽기 전용 쿼리 힌트
    • org.hibernate.readOnly` 힌트 사용시 엔티티를 읽기 전용으로 조회 가능하다.
    • 스냅샷의 저장단계를 생략할 수 있다고 한다.
      스냅샷?

      Hibernate 가 엔티티를 로드하는 경우 초기의 엔티티의 상태를 말한다고 한다.

      해당 스냅샷은 트랜잭션이 종료되는 경우 (자동 혹은 명시적인 플러시 시점) 엔티티가 변경되었는지 체크하는 과정에서 사용된다고 한다.

      더티체킹 라는 부분을 수행하지 않는다고 생각하면 된다.

      엔티티의 변경감지하는 로직을 수행하지 않는다.

    TypedQuery<Order> query = em.createQuery("select o from Order o", Order.class);
    query.setHint("org.hibernate.readOnly", true);
  1. 읽기 전용 트랜잭션의 사용
    1. 스프링에서 제공하는 @Transactional(readOnly = true) 어노테이션으로 트랜잭셔을 읽기 전용으로 설정
    1. 하이버네이트 플러시 모드가 수동 으로 설정되며
    1. 스냅샷 비교의 수행을 피해 성능의 향상을 도모가능하다고 한다.
  1. 트랜잭션 밖에서 읽기..?
    • 데이터 조회 목적만 있는 서비스 로직의 경우에는 트랜잭션없이 조회할 수 있다.
    • 플러시모드가 발생하지 않아 조회 성능의 향상이 가능하다.
    • 스프링에서는
      • @Transactional(propagation = Propagation.NOT_SUPPORTED)
      • 이 사용가능하다.

사용

  • 읽기 전용 트랜잭션과 쿼리 힌트 동시 사용 ( 또한 스칼라 조회 )으로
  • 조회의 성능을 극대화 할 수 있다.
    @Transactional(readOnly = true) // 읽기 전용 트랜잭션
    public List<DataEntity> findDatas() {
        return em.createQuery("select d from DataEntity d", DataEntity.class)
                 .setHint("org.hibernate.readOnly", true) // 읽기 전용 쿼리 힌트
                 .getResultList();
    }
    1. 트랜잭션 설정으로 플러시 모드 방지
    1. 엔티티 읽기전용 설정으로 조회시 메모리 사용량을 줄인다.

궁금한데..

  • 1번과 2번은 같은 행동을 하는게 아닌가?..
    • 찾아보니..
      • 1번에 대한 행동은
        • 트랜잭션 범위에 대한 설정이라고 합니다.
        • 해당 범위에 발생하는 DB 작업에 영향..
        • 커밋 시점의 플러시로 한번 - 즉, DB IO 한번으로 모든 쿼리를 수행하게 되는 것입니다.
      • 2번에 대한 행동은
        • 특정 쿼리에서 반환된 엔티티에 대한 설정입니다.
        • 즉 해당 쿼리 단일로 동작하는 성능의 최적화 작업이라고 볼 수 있습니다.
        • 해당 로드된 엔티티에 스냅샷을 저장하지 않는 부분에서의 성능의 최적화라고 볼 수 있습니다.

근데 DataJpa 에서 만약에 select 쿼리를 치는 경우에는 어떻게 제어해주는 걸까 고민이 생겼습니다.

  • 찾아보니.. DataJpa 는 별도 2번에 대한 스냅샷

Uploaded by N2T