-
[Spring JPA] 성능 개선을 하기 위해 당신이 알아야 할 상식Back End/Spring Data JPA 2022. 1. 1. 20:50
패켐에서 패키지형식으로 들으니 아무래도 JPA 관련하여 충분한 내용을 숙지하지 못한것 같다.
(패켐에서는 Spring Data JPA 에 대해서만 다뤘다 ㅠㅠ...)
이러한 상태에서 성능개선을 위해 머리를 굴리려니
JPA 에 대해서도 알아볼게 많았고, QueryDSL 도 마찬가지였다.
저처럼 Spring Data JPA는 사용하고 계시지만, 기초가 부족한 분들을 위해 좋은글이 되었으면 한다.
+) 추가적인 정보공유는 언제든지 환영합니다. 우리 모두 정보를 공유하며 같이 성장해보아요...!
* 심도 있게 다루지는 않을 것이며, 키워드들을 던지는 방식으로 본 포스팅을 작성하려합니다.
[알아두어야 하는 상식]
1. flush 와 commit 의 차이점
2. DB와 영속성 컨텍스트의 동기화 시점 (commit, flush, JPQL)
* repository.findAll() 또한 JPQL의 호출이다.
* repository.findById()는 영속성 캐시에 해당 값이 있을 경우에만 JPQL 호출이 아니다.
* JPQL이 호출되면 먼저 flush 를 호출하고 쿼리문을 실행한다.
3. QueryDSL 의 update 구문은 영속성 컨텍스트에 포함되지 않는다.
* 하지만 select 구문은 영속성 컨텍스트에 포함시킬 수 있다.
* QueryDSL 로 만든 구문은 JPQL 로 변환된다
는 글을 본적이 있다. (사실로 확인됨)* 위의 글이 사실이라면, 영속성 컨텍스트는 setter와 같이 객체를 직접 변경시켜야 변경사항이 인지된다.
4. flush() 시점에 EntityManger 는 항상 컨텍스트의 스냅샷과 DB의 스냅샷을 비교한다.
5. @Transactional(readOnly=true) 는 강제로 flush() 하지 않는 이상 flush가 발생하지 않는다.
6. 읽기전용 쿼리 힌트를 사용하면 스냅샷을 보관하지 않는다.
* 대용량 데이터를 처리해야할 때, 메모리상의 이점을 얻을 수 있다.
7. JPA는 데이터베이스 SQL 힌트기능을 제공하지 않는다. 하이버네이트가 제공한다.
8. commit() 전까지는 쓰기지연의 효과를 가진다. (DB에 락이 걸리지않는다.)
9. 트랜잭션의 격리수준에 대한 이해
10. afterCommit() 에서는 아직 영속성이 정리되지않아 lazy loading 이 가능하다.
11. commit 시, flush 가 자동 호출된다.
12. 서브쿼리는 쿼리에서의 안티패턴이다. (by 배민 이동욱님)
13. JPA에서 IDENTITY 생성전략을 사용하면 Batch Insert가 비활성화 된다.
* 새로 할당할 PK 값을 미리 알 수 없기 때문에
* JdcbTemplate의 batchUpdate 사용 (Type-safe 포기)
* Exposed 라이브러리 사용
14. JPA의 사실과 오해 (https://developer-ping9.tistory.com/255)
15. repository.save()의 구현을 보면 if문으로 persist()와 merge()가 분기한다.
* 즉, flush()의 호출은 없다.
[실험해보아야 할 것]
1. QueryDSL 의 동적쿼리를 위한 연속적인 if 문과 영속성 컨텍스트의 스냅샷비교 중 뭐가 효율이 좋을까?
* 단위별로 쪼개면서 하지 않았을 때, 1만건 기준 2000배의 차이를 보인다고 한다. (QueryDSL 승)
* 대용량 데이터를 update 할 때, 특정단위(ex_ 100개)별로 영속성컨텍스트를 flush하고 clear한다면?
(이러면 메모리 우위는 QueryDSL 이겠지만, 속도는 영속성 컨텍스트가 우위일 것 같은데... )
2. QueryDSL 의 쿼리는 JPQL 인가? (맞다)
* QueryDSL의 SELECT 호출 직전, 객체를 변경시켰더니 스냅샷 비교로 인해 update가 날라갔다. (즉 flush()가 호출됨)
em.flush() - It saves the entity immediately to the database with in a transaction to be used further and it can be rolled back.
em.getTransaction().commit - It marks the end of transaction and saves all the chnages with in the transaction into the database and it can't be rolled back.
# Reference
1. QueryDSL -> JPQL -> SQL 이라는 주장
2. 영속성 캐쉬 다루기
3. 플러시 모드 옵션
4. 우테콘 이동욱님의 발표영상 정리한 글
5. 플러시 호출시기
728x90'Back End > Spring Data JPA' 카테고리의 다른 글
[Spring JPA] 슈퍼-서브타입 관계 모델링 (상속관계 매핑) (0) 2022.01.14 [Spring JPA] 단방향, 양방향 결정기준과 연관관계의 주인 (0) 2022.01.14 [Spring JPA] 트랜잭션 로깅하기, 테스트 실행환경 분리하기 (yml, properties) (0) 2021.12.24 [Spring JPA] JPA에서 Lazy loading 은 도대체 어떻게 이루어지는 걸까? (0) 2021.12.24 [Spring JPA] Spring Test 에서 Auditing 이 안될때 (@DataJpaTest) (0) 2021.12.24