먼저 JPA 힌트란,
SQL에는 Hint 라는 것이 있다.
그러니까,
SELECT employee_name FROM employees USE INDEX(employee_idx) WHERE department_id = 10;
Hint 라는 것은 어떤 명령을 처리하기 위해 최적화된 방법?을 지시해 주는 것이다.
mysql에서는 저렇게 use index로 힌트를 주로 제공한다고 한다.
use index말고도 여러 힌트들이 있다고 한다.
USE INDEX : 사용할 인덱스를 지정합니다.
FORCE INDEX: USE INDEX와 비슷하지만 더 강력합니다. 비용을 고려하지 않습니다.
IGNORE INDEX: 최적화 프로그램에 특정 인덱스를 무시하도록 지시합니다.
여튼, sql문에 쿼리 실행 방법에 대해 뭔가 최적화를 위해 미리 만들어 놓은 프로세싱 패턴을 지시하는 것이다.
JPQL에서도 그런 게 있다.
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String usernane);
이것이다.
@QueryHints라고 해서 안에 @QueryHint들을 넣어주면 된다.
그 중 하이버네이트가 제공하는 readOnly를 true로 해 줬다. 즉, 사용하기로 지정하면서 열어줬다.
나는 처음에 value="true"하길래 왜 저 쿼리 힌트쓴다고 명시해 주면 이미 저 힌트를 쓴다는 건데 왜 true를 넣어줘야 하는 거지? 라고 생각했는데,
false로 넣어준 것과 아예 저 QueryHint를 사용하지 않는 것에 처리하는 과정의 차이가 있다고 한다... 라고 하는데 맞나? chat GPT가 이랬다 저랬다 해서 모르겠다.
https://www.inflearn.com/questions/1083044
물어봤다.
여튼,
저렇게 하이버네이트에서 제공해주는 readOnly를 쓰면 어떻게 되냐면,
우리가 영속성컨텍스트에서 변경감지를 통해 자동으로 update쿼리가 나가게 하려면, 원본의 값을 캡쳐해놔야 한다. 그래야 뭐가 변경된건지 알 수 있는거니까.
그래서 메모리가 더 드는거다.
저렇게 캡쳐를 해 놓은 데이터도 따로 영속성 컨텍스트를 통하여 있어야 하고, 또 그런 변경감지를 위한 로직 또한 실행되어야 한다.
하이버네이트에서 제공하는 readOnly는 이러 한 부분을 생략시켜버리는 것이다.
그래서 최적화가 된다.
근데 요새는 GC성능도 좋고 해서 이런 부분들을 readOnly만 할 부분들을 모조리 저렇게 명시해 주며 쿼리힌트를 사용할 필요가 있을까? 하면은..
Redis등을 통하여 최적화를 꾀하는 게 더 좋아보인다.
이거는 정말 트래픽이 많은 api 몇개정도만 그냥 넣는거다. 그리고 그 정도면 Redis를 통해 최적화를 꾀하는 게..
여튼, 잘 사용하지는 않을 거 같고,
여러가지 join fetch, batch, Redis등으로 최적화를 하고,
저 부분도 성능테스트를 해 보고 효과적일 때 쿼리 힌트를 쓸 것 같다.
그 다음 Lock
락은 우리가 DB에서 배웠던 Lock 그거다
https://qwefdg3.tistory.com/563
간단히 설명하자면,
우리가 이 데이터의 트랜잭션 동안, 다른 세션이 손대지 못하게 하는 것이다.
근데 보면 알겠지만 트래픽이 많은 경우는 이거 걸어놓으면.. 좀 그렇다.
https://qwefdg3.tistory.com/558
여기가 LOCK에 대한 설명이 있다.
READ COMMITED가 보통 DB의 기본 설정인 것 같다.
여튼
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findLockByUsername(String usernmae);
이렇게 쓸 수 있고,
PESSIMISTIC_WRITE는 직역은 비관적인 쓰기인데, 말 그대로 쓰기,
이 트랜잭션 동안 다른 트랜잭션의 CUD를 막는다.
호출해보면
select
m1_0.member_id,
m1_0.age,
m1_0.team_id,
m1_0.username
from
member m1_0
where
m1_0.username=? for update
이렇게 for update 붙어서 나간다.
for update, 저 sql문은 직역은 업데이트를 위한, 이라는 뜻인데,
지금 업데이트 중이니 다른 것은 손 대지마. 라는 의미이다.
위에서 말한 PERSSIMISTIC_WRITE와 뜻이 맞다.
이 lock은 SpringDataJPA꺼가 아니라 JPA가 지원해 주는 것이다.
이번에 배운 것 들은 그렇게 실질적으로 쓸 일이 많지는 않을 것 같다.
'스프링데이터 + JPA > 스프링 데이터 JPA' 카테고리의 다른 글
21. Auditing (0) | 2023.11.24 |
---|---|
20. 확장기능. 사용자 정의 리포지토리 (0) | 2023.11.23 |
18. @EntityGraph (0) | 2023.11.23 |
17. 벌크성 수정쿼리 (0) | 2023.11.23 |
16. 스프링 데이터 JPA 페이징, 정렬 (0) | 2023.11.21 |