2023-04-17 @이영훈
JPA에서 fetch join과 join을 사용했을 때 실제로 수행되는 SQL에서 어떤 차이가 있는 지 기록으로 남깁니다
예를 들어, 게시물(Post)과 댓글(Comment)이 있는 블로그 애플리케이션이 있다고 가정해 봅시다.
각 게시물은 많은 댓글을 가질 수 있습니다.
이 구조에서 게시물과 댓글 사이의 관계는 일대다(One-to-Many) 관계입니다.
JPQL로 Join과 Fetch Join을 사용했을 때, SQL 쿼리가 어떻게 실행되는 지 확인해보겠습니다.
JPQL 쿼리
// 1. Join 사용
val postsWithComments: List<Post> = entityManager.createQuery(
"SELECT p FROM Post p LEFT JOIN p.comments c WHERE p.id = :postId"
)
.setParameter("postId", postId)
.resultList as List<Post>
Kotlin
복사
// 2. Fetch Join 사용
val postsWithComments: List<Post> = entityManager.createQuery(
"SELECT p FROM Post p LEFT JOIN FETCH p.comments WHERE p.id = :postId"
)
.setParameter("postId", postId)
.resultList as List<Post>
Kotlin
복사
SQL
각 예시에서 JPQL 쿼리를 실행할 때 생성되는 SQL 쿼리는 다음과 같습니다.
1.
Join 사용
SELECT p.*
FROM Post p
LEFT OUTER JOIN Comment c ON c.post_id = p.id
WHERE p.id = :postId
SQL
복사
위의 SQL 쿼리는 게시물(Post) 테이블과 댓글(Comment) 테이블을 INNER JOIN하여 해당 게시물의 모든 댓글을 가져옵니다.
2.
Fetch Join 사용
SELECT p.*, c.*
FROM Post p
LEFT OUTER JOIN Comment c ON c.post_id = p.id
WHERE p.id = :postId
SQL
복사
Fetch Join 사용시 SELECT에서 p.*, c.* 둘 다 가져오는 것을 확인할 수 있습니다. 반면 Join 사용시 p.* 로 게시글만 가져옵니다
Join과 Fetch Join 비교
Join
•
SELECT p.*
•
게시물을 가져온 후 댓글을 가져오기 위해 추가적인 쿼리를 실행합니다
•
방법은 지연 로딩(Lazy loading)을 사용하여 데이터베이스에서 필요한 시점에만 데이터를 가져옵니다
Fetch Join
•
SELECT p.*, c.*
•
게시물과 댓글을 함께 가져오기 때문에 한 번의 쿼리만 실행됩니다
•
fetch join은 즉시 로딩을 사용하기 때문에 join에 비해 더 많은 데이터를 가져오지만, 데이터베이스에서 불필요한 추가 쿼리를 실행하지 않으므로 더 효율적입니다
•
데이터베이스의 성능을 향상시키는데 도움이 됩니다