tails5555 / Our_Title_Academy_2018_Server

2018 우리들의 제목학원 - Back End[URL 리펙토링]
MIT License
2 stars 0 forks source link

Database 에서 Join을 할 때 탐색 속도에 어떤 영향을 미칠까? #3

Open tails5555 opened 5 years ago

tails5555 commented 5 years ago

JPA 에서 @ManyToOne 에 해당되는 객체를 이용하여 탐색을 하는 경우에는 Join 을 해서 탐색 하는 것과 마찬가지로 추측됩니다. 그렇지만 그 객체를 대놓고 탐색하는 건 외래키를 이용해서 탐색하면 끝이니 JPA 에서는 자동적으로 그 부분이 구현은 되어 있을 것으로 판단을 합니다.

하지만 @ManyToOne 에 해당되는 객체의 맴버 변수로 탐색하는 경우에는 JPA의 탐색 속도에 대하여 어떤 영향을 미칠지 구상을 하고 진행할 필요가 있습니다. 아무리 JPA 이라도 객체나 여러 가지 등으로 탐색할 수 있어도 역정규화 까지 구상을 해야 할 필요가 있기 때문입니다.

ex> Request 객체의 Category 객체 -> 문제는 없음. Title 객체에서 Request 객체의 Category 객체 -> 좀 Join 이 많아져서 탐색 속도에 영향이 있음.

이에 대한 아이디어 전구를 밝혀 봅시다.

shouwn commented 5 years ago

이 이슈는 여러가지 경우의 수가 존재합니다.

  1. 하나의 요청에 대한 응답으로 Title -> Request -> Category 를 조회할 경우
  2. 첫 번째 요청에 대한 응답으로 Title -> Request 까지 조회한 뒤에 그 다음 요청에 대한 응답에 Title -> Request -> Category 를 조회할 경우
  3. Category만 필요하거나 Request 만 필요한데 Title로 찾을 경우

먼저, 3번의 경우는 아무도 안 할 것이라 생각합니다. 불필요한 JOIN을 야기시킬 뿐입니다.

2번의 경우를 말하기 전에 JPA 가 어떻게 데이터를 DB에서 가져오는지 말씀드리겠습니다.

JPA 에서는 repository를 통해 데이터를 가져올 때에는 다음의 절차를 가집니다.

  1. 영속성에 데이터가 있는지 확인 1 - 1 영속성에 데이터가 있으면 그 데이터를 반환 1 - 2 없으면 2번 단계를 이행
  2. DB에서 데이터를 가져옴
  3. 가져온 데이터를 영속성화 함
  4. 영속성화 한 데이터를 반환

추가로 JPA는 영속성 데이터의 구분을 id를 통해서 합니다.

여기서 영속성이란 메모리 상에 데이터가 있다고 생각하시면 됩니다. (캐시입니다)

위의 단계를 통하기 때문에 Title -> Request 까지 가져왔다면 그 다음에 다시 세 개의 테이블을 찾는 것이 아니라 Category 하나만 찾기 때문에 문제가 없습니다.

1번의 경우에는 어처피 요청을 할 때 모두 가져와야 하기 때문에 이 이슈에는 해당되지 않는다고 보았습니다.

JPA 를 사용할 때 가장 큰 이슈는 one to many 에서 야기되는 N + 1 문제입니다. many to one 과 one to one은 큰 이슈가 되지 않습니다.

그리고 기본 fetch 방식은 LAZY 이기 때문에 레퍼지토리에서 one to many 를 사용할 경우 그냥 가져오는 것이 아닌 JPQL 로 join fetch 를 해주는 것이 N + 1 문제를 해결할 수 있습니다.

tails5555 commented 5 years ago

답변 감사드립니다 😃

Thanks To 에 기재 해 드리겠습니다 🙆‍♀️