카테고리 없음

코드 최적화확인

로드존슨 2023. 4. 9. 17:41
728x90

문제점 1. Token 인증시 user를 조회하고, 그 이후 또 user를 조회하는 구조 

문제점 5. 데이터 베이스로 날라가는 Query들은 최적화가 되었을까?

에 해당하는 코드들은 확인해보고  현 코드의 문제점을 확인해보면  불필요한 쿼리가 있는지 확인하여 리팩토링을 진행한다.

알람리스트를 호출하는 로직을 보게되면  DB I/O는 3번이다. 

    @Transactional
    public Page<Alarm> alarmList(String userName, Pageable pageable) {
        UserEntity userEntity = userRepository.findByUserName(userName).orElseThrow(() -> new SimpleSnsApplicationException(ErrorCode.USER_NOT_FOUND, String.format("userId is %d", userId)));
        return alarmEntityRepository.findAllByUser(userEntity, pageable).map(Alarm::fromEntity);
    }

1. jwt 필터를 통해 DB I/O 발생

2.alarmList 메소드를 통해 user 정보를 확인하는 DB I/O 발생

 

3.alarmlist 를 조회하는 DB I/O발생한다.

 

 

쿼리 최적화를 위해 코드 리팩토링을 해본다. 

 

    @Transactional
    public Page<Alarm> alarmList(Integer userId, Pageable pageable) {
        return alarmEntityRepository.findAllByUserId(userId, pageable).map(Alarm::fromEntity);
    }
@Repository
public interface AlarmEntityRepository extends JpaRepository<AlarmEntity, Integer> {

    Page<AlarmEntity> findAllByUserId(Integer userId, Pageable pageable);
    Page<AlarmEntity> findAllByUser(UserEntity user, Pageable pageable);

}

 

 

USER 와 ALARM 의 연관관계는 일대다 관계이다. 그렇기에 연관관계로 인해 연관된 쿼리가 진행이 되는데 

한번의 쿼리를 갖고오는거 같지만 

 

1)SELECT * FROM "alarm" 을 통해 알람리스트를 가져오고

2)SELECT * FROM 'user" WHERE id=9 을 통해 id가 9인 유저의 알람리스트 총 2개의 쿼리가 호출된다. 

 

user 가 사용이 되든 안되든 무조건 2개의 쿼리호출된다.

이는 JPA 의 연관관계를 지연로딩을 통해 해결할 수 있다.

그런데 실상 LAZY로 하게되면 불필요한 쿼리를 막을 뿐이지 쿼리의 호출수를 줄일려면 네이티브 쿼리를 작성해야한다.

public class AlarmEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id 

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private UserEntity user;

 

JPA에서는 영속성관리를 통해 데이터의 라이프사이클을 어플리케이션 내에서 진행한다.

변경이 되는 부분을 영속성관리를 통해 체크를 한다.그렇다면 영속성관리를 통해 어떤 작업이 선제되어야 할까??

바로 데이터베이스에서 데이터를 가져와야한다.

근데 "삭제" 같은 경우는 그냥 삭제만 하면되는데 기본 아래와 같이 쓰지 않고 deleteAllByPost 메소드로 작성시 데이터를 가져와서 비교 확인해보고 이를 삭제한다. 굉장히 비효율적이다.!!

1)데이터를 가져와서 

2)삭제할 데이터를 확인해서 삭제한다

그래서 JPA에서 제공하는 DELETE를 사용하지 않고 쿼리작성을 통해 진행한다.

    @Transactional
    @Modifying
    @Query("UPDATE CommentEntity entity SET removed_at = NOW() where entity.post = :post")
    void deleteAllByPost(@Param("post") PostEntity post);

 

728x90