DynamicUpdate를 찾던 중 원하는 컬럼만 변경하는데 효율적이라고 생각했는데,
DynamicUpdate을 쓰지 않고 항상 모든 컬럼을 변경하는게 효율적이라는 시각을 보고 알아보게 됐다!
@DynamicUpdate
@DynamicUpdate는 JPA에서 특정 엔티티 클래스에 사용 가능한 어노테이션이다.
이 어노테이션을 붙이면 업데이트할 때, 실제로 변경된 컬럼만을 업데이트하는 쿼리를 만들어주는데, 즉, 전체 컬럼을 모두 업데이트하는 대신, 변경이 일어난 필드만 업데이트하도록 최적화해주는 역할을 한다.
기본적으로 JPA는 엔티티가 변경될 때, 해당 엔티티의 모든 필드 값을 포함한 UPDATE 쿼리를 생성한다.
예를 들어, User 엔티티에서 name 필드만 변경하더라도, 기본 동작은 UPDATE user SET name = ?, email = ?, age = ? WHERE id = ?와 같이 모든 필드를 업데이트한다.
이와 반대로, @DynamicUpdate를 사용하면 실제 변경된 필드만 업데이트 쿼리에 포함된다.
User 엔티티에서 name 필드만 변경되었을 때, UPDATE user SET name = ? WHERE id = ?와 같이 필요한 필드만 쿼리에 포함된다.
@DynamicUpdate의 장점
1. 성능 최적화: 불필요하게 전체 필드를 업데이트하지 않고, 변경된 필드만 업데이트하기 때문에, 데이터베이스로 전송되는 데이터 양이 줄어든다.
2. 업데이트 시 충돌 방지: 여러 클라이언트가 동시에 특정 엔티티의 다른 필드를 업데이트할 때, 불필요한 충돌이 줄어든다.
예를 들어, 한 클라이언트가 name을 수정하고 다른 클라이언트가 email을 수정할 경우, @DynamicUpdate 덕분에 서로의 필드에 영향을 미치지 않는다.
@DynamicUpdate의 단점
@DynamicUpdate를 사용하면 쿼리 캐시 효율이 떨어질 수 있다고한다.
JPA는 결국 내부적으로 JDBC와 PreparedStatement를 사용하는데, 이때 PreparedStatement는 SQL 쿼리 구문을 캐시해서 동일한 쿼리 구문을 재사용하는 방식으로 성능을 최적화한다.
1. PreparedStatement 캐싱 저하: @DynamicUpdate를 쓰지 않으면 쿼리 구조가 일정해서, PreparedStatement가 이를 캐시에 저장해두고 반복 사용 가능하다. 예를 들어, 매번 UPDATE user SET name = ?, email = ? WHERE id = ?와 같은 구조를 재사용한다.
2. 쿼리 다양화로 인한 캐시 히트율 저하: 반면 @DynamicUpdate는 변경된 필드만 포함한 쿼리를 만든다. 그래서 한 번은 name만, 또 다른 번에는 email만, 또는 name과 age만 포함된 쿼리를 각각 새로 생성할 수 있다. 이 경우 매번 쿼리가 달라져 캐시 히트율이 떨어진다.
즉, @DynamicUpdate가 쿼리를 매번 다르게 만들기 때문에, 동일한 쿼리 구문이 캐시되기 어렵고, 이는 성능 저하로 이어질 수 있다.
결론
@DynamicUpdate는 필요한 경우에만 신중히 사용하는 것이 좋다고한다.
전체 업데이트가 불필요하거나, 동시성 문제로 인해 특정 필드만 업데이트하는 게 유리할 때는 효율적이고,
반대로, 쿼리 캐싱이 중요한 경우에는 캐시 히트율이 낮아져 성능 저하가 발생할 수 있기때문에 자제하는게 좋을 것 같다.
따라서, 데이터베이스 쿼리 성능과 캐시 효율성을 고려하여 상황에 맞게 사용하는 것이 최적의 성능을 얻는 방법으로 보인다 !