JPA로 실험을 하나 해보았다.

Hooman
5 min readNov 5, 2023

--

select문이 여러번 날아가는 문제 때문에 여러가지를 찾아보다가 실험을 하나 해보았다. fetch join 하는 것과 select문 여러개를 날리는 것 중에 무엇이 더 빠를까 라는 의문이 들었기 때문이었다.

그래서 해보았다.

저 두 메서드를 비교해볼 것이다.

비교를 위해 테스트 코드를 작성했다.

@Test
public void AccountTest() {

System.out.println("AccountTest 시작");

em.clear();

Long start1 = System.currentTimeMillis();

Account account = memberRepository.findStudentById("mirror111").get();

DefaultInfoDto dto = new DefaultInfoDto();

dto.setStudentName(account.getStudent().getName());
dto.setSchoolName(account.getStudent().getSchool().getSchoolName());
dto.setClubName(account.getStudent().getClub().getName());
dto.setPositionName(account.getStudent().getPosition().getName());
dto.setStudentType(account.getStudent().getType().name());

System.out.println("dto1: " + dto.toString());

Long end1 = System.currentTimeMillis();

// Assertions.assertThat(account.getId()).isEqualTo("mirror111");

em.flush();
em.clear();

System.out.println("직접 만든 쿼리 실행 시간: " + (end1 - start1));

System.out.println("AccountTest 끝");
}

@Test
public void findStudentInfoByAccountIdTest() {
System.out.println("findStudentInfoByAccountIdTest 시작");

em.clear();

Long start2 = System.currentTimeMillis();

Account account2 = memberRepository.findAccountById("mirror111").get();

DefaultInfoDto dto2 = new DefaultInfoDto();

dto2.setStudentName(account2.getStudent().getName());
dto2.setSchoolName(account2.getStudent().getSchool().getSchoolName());
dto2.setClubName(account2.getStudent().getClub().getName());
dto2.setPositionName(account2.getStudent().getPosition().getName());
dto2.setStudentType(account2.getStudent().getType().name());

System.out.println("dto2: " + dto2.toString());

Long end2 = System.currentTimeMillis();

em.flush();
em.clear();

System.out.println("find 메서드: " + (end2 - start2));

System.out.println("findStudentInfoByAccountIdTest 끝");

}

둘 다 Account 엔티티의 id 값을 가지고 Student 엔티티에 접근해서 School, Club, ClubPosition 엔티티에 추가적으로 접근해 데이터를 반환하는 코드다.

EntityManager.find() 메서드는 조인 없이 연속적으로 select문을 날리는 것을 미리 확인했다.

나는 조인해서 한 번에 가져오는 쪽이 더 빠르지 않을까 하는 예상을 했다.

한 번 결과를 보자.

오히려 select문을 여러개 날리는 EntityManager.find()쪽이 실행 속도가 더 빨랐다.

select문들이 하나의 트랜잭션 안에서 움직여서 그런것일까?

아니면 내가 쿼리를 잘못 짠 것일까 아니면 JPQL을 해석하는데 추가적인 리소스를 잡아먹는 탓일까…

이유를 알기 위해선 더 열심히 공부해야할 것 같다.

--

--