개요
SQL에서 Hint를 사용하듯이 JPA에서도 JPA 구현체에 힌트를 전달할 수 있다.
조회만 사용하기(Read Only)
- JPA 에서 데이터를 조회하게 되면 영속성 컨텍스트에 저장되어 관리된다.
- 그리고 그 값을 수정하게 되면 drity checking 이 일어나게 된다.
- JPA 는
원본 객체와 변경된 객체를 비교하고 DB 에 Update 쿼리를 날린다.
- 이는
원본 객체와 변경된 객체 2개의 객체를 관리해야 하기 때문에 메모리가 낭비된다.
- Hint 를 사용하여 영속성 컨텍스트에 저장되는 것을 방지하고, 혹시 모를 변경 사항에 대해 Update Query 가 날라가 메모리 낭비를 하지 않도록 할 수 있다.
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUserName(String userName);
@Test
void queryHint() {
//given
Member member1 = new Member("member1", 10);
memberRepository.save(member1);
entityManager.flush();
entityManager.clear();
//when
Member findMember = memberRepository.findReadOnlyByUserName("member1");
findMember.changeUserName("member2"); // update 발생 X
entityManager.flush();
}
- 이름이 member1 인 회원을 찾고 member2 로 이름을 변경하였지만 readOnly 가 true 로 설정되어 Update 쿼리는 발생하지 않는다.
- readOnly 가 true 로 되어 있으면 스냅샷을 만들지 않는다. (변경 무시)
- 이처럼 변경 사항이 DB 에 반영될 필요 없이 오직 조회만 필요할 때 readOnly 옵션을 사용할 수 있습니다.
조회만 한다면 Hunt 를 무조건 사용하는 것이 좋을까?
- Hunt 를 사용하여 극적인 성능 최적화 효과를 보기는 어렵다.
- 그렇기 때문에 무조건 사용하는 것보다 성능 테스트 후에 조회 성능에 문제가 있거나 취할 수 있는 이점이 있는 경우에만 사용하는 것이 바람직하다.
- 진짜 조회 성능이 딸린다면 Redis 캐시 등을 통해서 읽기 성능을 향상 시켜야 할 것이다.
Lock
- JPA 에서는 보통 SELECT 후에 UPDATE 를 날리기 때문에 멀티 스레드 환경에서 값의 **
정합성**을 보장하기 어렵다.
- Lock 에는 여러 종류가 있지만 위와 같은 상황에서는 **비관적 잠금(Pessimistic Lock, 동일한 데이터를 동시에 수정할 가능성이 높다는 비관적인 전제로 잠그는 거는 방식)**을 사용해야 한다.