사건의 발단은 이랬다.
내가 조건에 맞춰 queydsl을 이용해서 원하는 데이터를 DTO로 뽑아서 조회하고싶었다.
DTO로 뽑아오는 도중 많은 오류를 만났었고, 어떤 오류인지, 어떻게 해결하는지 직접 검색하고 찾아보면서 문제를 해결해 나가고 있다.
그러던 와중에 문득 데이터를 어떻게 뽑아오지? 라는 생각을 했다.
예를들어서 post 와 recommend 라는 테이블들이 각각 있으면 이들은 1:M // M:1 (양방향) 관계를 맺고 있다.
내가 원하는 것은 각각의 post에 맞춰서 recommend를 count 해오는 것이였는데, 어떻게 이를 count 해올 수 있을까? 라는 생각이 들었다.
먼저 where 조건절에 post.id.eq(recommend.post.id) 이렇게 조건을 주니 내가 원하는 데이터가 나오지 않았다.
이를 어떻게 해결할 수 있을지 생각을 했다.
다른 query를 통해서 해당 id 값에 따라 또 다른 query를 발생시켜 count 해온 recommend 숫자를 붙여줘야 하나? 라는 생각, 서브쿼리를 이용해야하나? 라는 생각 외에는 다른 생각들이 많이 들지 않았다. ( 아직 경험도 부족하고 공부가 많이 필요함을 느꼈다...)
나는 후자인 select 절의 서브 쿼리를 선택했고, 이 전에 querydsl을 공부할 때, 성능 관점에서 서브쿼리는 좋지 못하다 이야기를 얼핏 들었던 적이 있어서, 해당 내용을 복습 차원에서 정리해보려고 한다.
( 그런데 내가 원하는 결과물인 단 1방으로 끝나버렸다???)
일단 서브쿼리(subQuery)는 어떤 테이블의 일부를 가지고 오기 위해서 해당 query문이 실행될 때, 또 다른 query문을 발생시키는 것이다.
서브 쿼리의 장점은 간편하게 내가 원하는 데이터를 가지고 올 수 있다는 점이 있으나, 연산의 비용이 추가로 발생하고, 최적화를 받을 수 없다. 또한 메인 쿼리가 복잡해지는 단점이 발생한다.
이를 조금 더 자세히 정리해보자
1. 추가적인 연산비용 발생
서브 쿼리는 말 그대로 가상의 테이블을 만드는 것이라, 서브쿼리에 접근하려고 하면 해당 구문을 만들게 되고, 이로 인해 연산 비용이 늘어난다. ( 계속 계속 서브 쿼리를 날림 해당 메인 쿼리문을 실행할 때마다.)
2. 최적화를 받을 수 없다.
서브쿼리엔 메타 정보가 담겨있지 않다( 명시적인 제약이나, 인덱스가 작성되어 있지 않다. ) 그래서 내부적으로 복잡한 연산 수행시 결과 크기가 큰 서브쿼리를 사용할 때 성능 상의 이슈가 발생할 여지가 있다.
3. 복잡한 쿼리
간단한 데이터를 가지고 올 때는 못 느낄 수 있지만, 만약에 내가 복잡한 데이터를 가지고 와야한다면???
결국 서브쿼리의 내용이 복잡해지면 메인 쿼리의 가독성도 떨어질 것이다.
그래서 효과적인 서브 쿼리를 사용하려면 어떻게 해야할까??
join 사용 시 사전에 결합 레코드 수를 압축하게 된다면 join 레코드의 수를 줄일 수 있다.
해당 내용에 관해선 아래 참고 블로그에 더 자세하게 나와있으니 참고를 하는 것이 좋겠다.
< 참고 >
https://doing7.tistory.com/127
https://schatz37.tistory.com/3
'스프링 > JPA' 카테고리의 다른 글
JPA 데이터베이스 초기화 전략 (5가지 ) (0) | 2023.03.22 |
---|---|
@Transactional 복습 그리고 더 나아가기 (readOnly) (0) | 2023.03.11 |
만약 대량의 데이터를 지워야 할 일이 있다면??? (JPA) (0) | 2023.01.14 |
cascade = CascadeType.REMOVE ? orphanRemoval = ture? (0) | 2023.01.06 |
JPA - 영속성 컨텍스트 (2022.12.11 추가) (0) | 2022.12.09 |