Replies: 1 comment
-
서브 쿼리가 추가적인 쿼리보다 더 효율이 좋을까에 대한 고민도 드네요 .. 더 좋은 방법 있으면 의견 주시면 감사합니다 :) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
문제
유저의 정보가 필요한 상황이라면 항상 팔로워 수가 필요한 것을
UI
를 통해 확인할 수 있다.현재 작성된 코드에서는 Member 도메인에서 Follow 도메인과
@OneToMany
양방향 연관관계를 설정하여 팔로워 수가 필요할 때 Follow 목록의size
를 호출하여 개수를 확인한다. 코드는 아래와 같다.위의 방법을 사용함으로 발생할 수 있는 문제는 아래와 같다.
1. 팔로잉, 팔로워 목록을 조회하면서 N+1 문제가 발생할 수 있다.
특정 유저의 팔로잉 유저 목록을 조회할 때 각 유저의 팔로워 수를 알아야 하기에 추가적인 쿼리가 발생하게 된다.
2. 불필요한 메모리를 사용하게 된다.
필요한 정보는 단지 팔로워 수인데, Follow 도메인의 모든 필드를 불러오기에 불필요한 정보를 가져오게 되므로 불필요한 메모리를 사용하게 되는 문제가 발생한다.
1. fetch join을 사용한다.
fetch join을 사용하게 되면 Member를 조회하면서 Follow 목록도 함께 가져오기에 추가적인 쿼리가 나가는 것을 막을 수 있다. fetch join은 Lazy Loading으로 설정되어있다고 하더라도 한번의 쿼리로 가져올 수 있다는 특징이 있다.
하지만 fetch join을 사용하면 paging을 적용할 수 없다는 단점이 있다. join을 하게되면 Member 기준으로 Follow를 조인하게 되기 때문에 데이터 수가 변하고 JPA는 어떤 데이터를 기준으로 페이징을 해야하는지 알 수 없다. 따라서 모든 데이터를 불러와 메모리에 올려두고 페이징을 하게되는 불상사가 발생하게 된다.
default batch fetch size 설정을 통해 paging과 N+1 문제를 적절히 해결할 수 있지만, 여전히 모든 데이터를 불러와서 불필요한 메모리를 사용한다는 문제는 남아있다.
2. @formula를 사용한다.
@formula는 하이버네이트 기술로 데이터베이스 질의값을 가상의 읽기 전용 컬럼으로 매핑하게 된다. 데이터베이스에 따라 영향을 받는 SQL문 작성이 필요하고, 하이버네이트 기술이기에 JPA 구현체로 하이버네이트를 사용하지 않는 경우 사용할 수 없다.
위의 코드로 팔로우 수를 조회하게 된다면 아래의 쿼리가 추가적으로 나가게 된다.
원래라면 IN절을 사용하지 않고 위의 쿼리가 Member 수만큼 나가게 되지만
default batch fetch size
를 적용해두었기에, IN절로 나가게 된다.페이징으로 멤버를 조회하기에 많아야 2번 정도의 쿼리가 추가적으로 발생하지만, 그럼에도 추가적인 쿼리가 나가는 비용을 무시할 수 없다.
@formula를 사용하면 Member를 조회하는 쿼리 서브 쿼리로 해당 쿼리가 함께 수행되기에 추가적인 쿼리없이 하나의 쿼리로 팔로워 수를 가져올 수 있다.
또한 다른 데이터는 가져오지 않고 팔로워 수만 가져오기에 불필요한 메모리를 사용하지 않는다는 장점도 있다. 기존에 양방향 연관관계로 팔로워 수를 구하는 방법에는 정말 양방향 연관관계가 필요한가에 대한 고민도 하게 되는데(양방향 연관관계인 경우 양방향 다 작업이 필요하기 때문) 이 방법은 그런 고민도 해결할 수 있다.
위 처럼 사용하게 되면 항상 즉시 조회하게 되는데, 즉시 조회하지 않고 사용할 때 쿼리를 날리는 방법도 존재한다. 현재 프로젝트에서는 Member 조회가 필요한 상황에서는 항상 팔로워 수가 필요하기에 즉시 로딩되도록 설정하였다.
Beta Was this translation helpful? Give feedback.
All reactions