티스토리 뷰

이번에 작성할 글은 query dsl 을 사용하여 fetch join 을 사용할시에 limit 를 사용할시 주의하여야 할 점에 대하여 정리하고자 합니다!

블로그 코드는 GitHub 에서 볼 수 있습니다


최초 데이터

USER TABLE (ONE) 3개의 데이터 존재

INSERT INTO USER (idx, user_id, password, name, email) VALUES (1, 'joonghyun', 'pwd1', '최중현', 'wndgus@gmail.com');
INSERT INTO USER (idx, user_id, password, name, email) VALUES (2, 'dakim', 'pwd2', '김다애', 'ekdo@gmail.com');
INSERT INTO USER (idx, user_id, password, name, email) VALUES (3, 'jangsi', 'pwd3', '장시후', 'tlgn@gmail.com');


ARTICLE TABLE (MANY) 8개의 데이터 존재

INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(1, 1, '내용1', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(2, 1, '내용2', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(3, 1, '내용3', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(4, 1, '내용4', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(5, 2, '내용5', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(6, 2, '내용6', '01');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(7, 3, '내용7', '02');
INSERT INTO ARTICLE (idx, user_idx, content, category) VALUES(8, 3, '내용88', '02');


위 2개의 TABLE 을 가지고 LEFT JOIN 쿼리문은 보통 이렇게 작성하실 겁니다.


SELECT * FROM USER A LEFT JOIN ARTICLE B ON A.idx = B.user_idx LIMIT 2;

@Override
public List<User> findWithArticle_not_fetch_join() {
return this.queryFactory.selectFrom(user)
.leftJoin(user.articles, article)
.limit(2)
.fetch();
}

- 실행되는 query dsl 쿼리 실행문 -

select

        user0_.idx as idx1_3_,

        user0_.email as email2_3_,

        user0_.name as name3_3_,

        user0_.password as password4_3_,

        user0_.user_id as user_id5_3_ 

    from

        user user0_ 

    left outer join

        article articles1_ 

            on user0_.idx=articles1_.user_idx limit ?


여기에서 나오는 결과는 아래와 같습니다.



하지만 여기에서 fetch join 을 사용하면 어떻게 되는지 보겠습니다.

@Override
public List<User> findWithArticle_fetch_join() {
return this.queryFactory.selectFrom(user)
.leftJoin(user.articles, article)
.fetchJoin()
.limit(2)
.fetch();
}

위와 동일한 query dsl 문이며 left join 밑에 fetch join 이 추가 되었습니다.

- 실행되는 query dsl 쿼리 실행문 -

select

        user0_.idx as idx1_3_0_,

        articles1_.idx as idx1_0_1_,

        user0_.email as email2_3_0_,

        user0_.name as name3_3_0_,

        user0_.password as password4_3_0_,

        user0_.user_id as user_id5_3_0_,

        articles1_.category as category2_0_1_,

        articles1_.content as content3_0_1_,

        articles1_.user_idx as user_idx4_0_1_,

        articles1_.user_idx as user_idx4_0_0__,

        articles1_.idx as idx1_0_0__ 

    from

        user user0_ 

    left outer join

        article articles1_ 

            on user0_.idx=articles1_.user_idx      LIMIT 가 존재하지 않습니다 ! 즉 모든 데이터를 풀스캔하여 조회 하게 됩니다. 주의..!!


즉 one to many 관계 에서 fetch join 후 limit 를 사용하게 되면 모든 데이터를 one to many 관계에 맞추어 fetch 가 이루어지고 난 후에 2개의 one (USER TABLE) 의 값을 리턴해 줍니다.


아래는 결과 입니다.

2개의 USER 도메인에 ARTICLE LIST 가 모두 fetch 되었으며 그 후에 2개의 USER 도메인만 리턴 됩니다.


결론

fetch join 시 LIMIT 를 사용할때에는 query dsl 에서 모든 데이터를 조회후 LIMIT 에 맞추어 잘라주고 있습니다. 이를 꼭 확인하여야 합니다..! 


WHERE절이 존재할경우 WHERE 절에 맞추어 데이터가 먼저 추출되고 그후에 추출된 데이터 기반으로 fetch join 이 이루어지고 그후에 LIMIT 에 맞추어 데이터를 리턴합니다.


처음에는.. fetch join 시 n+1 문제를 해결해 준다고 아무생각 없이 여기저기에 붙여서 사용하였습니다.. 항상 생성되는 쿼리를 확인하고 쿼리플랜을 확인해가며 개발을 하여야 할 것 같습니다.!


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함