N+1 문제 해결기

Hyuk·2023년 9월 3일
0

HappyScrolls 개발기

목록 보기
5/24
post-thumbnail

이전에 살펴보기로 했던 N+1 문제를 개선해 볼 예정이다.

Article을 살펴보면

이렇게 ManyToOne으로 Member를 갖고 있다.

게다가 페이지 당 10건의 Article을 가져오기 때문에 페이징에 필요한 쿼리에다 추가로 10개의 쿼리를 날리는 것으로 보인다.

N+1 문제는 예전 글에서 살펴봤던 것 처럼 페치 조인을 사용하면 된다.
https://velog.io/@chs98412/N1-%EB%AC%B8%EC%A0%9C-fetch-join

어떤 조인이던 어쨌든 조인을 해서 쿼리 수를 줄이는게 목적이니 지난번에 페이징을 개선했던 쿼리에 조인을 하면 되지 않을까 싶었다.

Hibernate: select member0_.id as id1_5_, member0_.email as email2_5_, member0_.nickname as nickname3_5_, member0_.point as point4_5_, member0_.thumbnail as thumbnai5_5_ from member member0_ where member0_.email=?
Hibernate: SELECT * FROM Article JOIN Member ON Article.member_id=Member.id where Article.id> ? limit ?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?
Hibernate: select member0_.id as id1_5_0_, member0_.email as email2_5_0_, member0_.nickname as nickname3_5_0_, member0_.point as point4_5_0_, member0_.thumbnail as thumbnai5_5_0_ from member member0_ where member0_.id=?

그런데 기대와는 다르게 쿼리가 추가로 나가는 것을 알 수 있었다.

검색해보니, 네이티브 쿼리로는 jpa 연관관계에 딸려온 것을 가져올 수 없고 하이버네이트를 사용해야한다고 한다.

그래서 어쩔 수 없지만 jpql을 사용하기로 했다.

그런데 저 쎄한 빨간줄.. (limit 옆에 살짝 보인다.)

jpql을 쿼리로 작성할 때 limit을 사용할 수 없다고 한다…

따라서 나에게 두가지 선택지가 남은것 같다.

QueryDSL을 사용할지, 아니면 아예 연관관계를 없앨지…

아마 연관관계를 없앨 것 같다.
⇒ 연관 관계를 없앴다가 결국 다시 되돌렸다 ㅎ..
연관관계 해소
나중에 분산 시스템으로 가면 연관관계를 사용할 수 없다는 이야기도 들었고, 연관관계가 주는 이득보단 그로 인해 생긴 문제가 더 많기 때문에 지양한다고 한다.

물론 지금 내 상황에서는 연관관계를 없애면 .get으로 접근하던 것들은 그러지 못한다.

그치만.. 해보고 싶긴 해서 아마 현재 해결하려는 Article 쪽에만 연관관계를 없앨듯 하다.

JPA 연관관계는 다른 곳들에서 신나게 사용하고 있으니 이번 프로젝트에서는 사용하지 않고 해보는것도 좋을 것 같다는 생각을 했다.

profile
🙂 🙃 🙂 🙃

0개의 댓글