JPA를 활용하면서

개발개발·2021년 4월 12일
0

cron을 활용해서 정해진 시간마다 DB에서 정보를 재귀적으로 탐색하던중 쓰레드를 처리하는데 시간이 너무 오래 걸린다는 것을 발견했다.

성능 향상을 위해서 재귀 메소드를 query로 변경하기로 했고 성능을 테스트해보기로 했다.

재귀 메소드와 쿼리의 속도 측정
1. Java Jpa 재귀메소드
2. mysql recursive cte
3. 각각 작업시간을 측정한다.

Java

// 활동중인 자신의 후임들이 몇명인지 재귀적으로 찾아낸다.
public class UnitEntity {
	int id; // id
   	int upperUnitId; // 선임
       boolean active; // 현재 활동 여부
}

// 재귀 메소드
// 재귀는 나의 후임이 없으면 멈춘다.
public class RecursiveFind{
	
   private static int unitCount = 0;
   
        public void countMyUnderUnit(int unit_entity_id) {
        	// 1. parameter를 선임으로 하는 unit을 찾는다.(parameter의 후임 찾기)
               List<UnitEntity> under_unit_list = unitRepository.findUnitEntitiesByUpperUnitId(unit_entity_id);
               if(under_unit_list.size == 0) return;
               // 반복문을 통해 원하는 조건을 확인한다.
               for (UnitEntity unit : under_unit_list) {
               	// 2. 활동 여부를 판단해서 숫자를 센다.
                	if(unit.getActive){
                   	unitCount++;
                   }
                   // 3. 반복 !
                   countMyUnderUnit(unit.getId());
               }
           }
}

mysql


with recursive cte (id, upperUnitId, active) as
(
select     id,
           upperUnitId,
           active
from       unit upper_unit
	where upper_unit = <parameter 입력!>
union all
select     
	   id,
           upperUnitId,
           active
from       unit under_unit
inner join cte on under_unit.upeerUnitId= cte.id
)
select id, upperUnitId, active from cte where active = 1;

구동 환경에 따라서 차이가 있겠지만 메소드 활용보다 쿼리가 압도적인 성능을 보여주었다.

jpa를 활용하면 대량의 데이터를 처리하는데 불리하다는 것을 알게 되었다.
그래서 대용량 조회 및 데이터 수정,삭제는 nativeQuery를 사용하는 것이 더욱 낫겠다는 결론을 내렸다.

+@ repository에서 update와 delete를 사용할때
@Modifying
@Transactional
Anotation을 붙여야 한다.

ex)

public interface UnitRepository extends JpaRepository<UnitEntity, Integer> {
	// error 발생
    @Query(value = "update
    			unitEntity set upperUnitId = :upperUnitId
                    where id = :id", nativeQuery = true)
    void updateQuery(@Param("id")int id ,@Param("upperUnitId")int upperUnitId);
    
    // 수정
    @Modifying
    @Transactional
    @Query(value = "update
    			unitEntity set upperUnitId = :upperUnitId
                    where id = :id", nativeQuery = true)
    void updateQuery(@Param("id")int id ,@Param("upperUnitId")int upperUnitId);
    
}
  • 테스트를 하던 중 외래키가 걸려있음에도 nativeQuery를 사용하면 삭제가 되었다. mysql에서 똑같은 query를 실행했을때와는 다르게...

조금더 테스트를 진행해보고 결과를 남겨야겠다.

profile
청포도루이보스민트티

0개의 댓글