본문 바로가기

DB

[DB] 정규화

정규화

  • 중복을 최소화하게 데이터를 구조화하는 프로세스
  • 중복을 제거, 한 곳에서만 데이터를 관리하게 설계
  • 읽을 때는 항상 원본 데이터를 참조
  • 읽을 때 참조가 발생하기 때문에, 조회의 성능을 포기하고 쓰기의 성능을 올린다.
  • 테이블 설계 관점에서, 조회와 쓰기 사이의 트레이드 오프

 

비정규화

  • 정규화의 반대
  • 중복을 허용하고 참조 없이 읽기가 가능하다.
  • 쓰기의 성능을 포기하고 읽기의 성능을 올린다.

 

Follow 기능을 구현한다고 가정할 때, Flow Entity를 다음과 같이 만들 수 있다.

@Getter
public class Follow {
   final private long id;
   final private String fromMemberNickname;
   final private int fromMembeAge;
   final private String toMemberNickname;
   final private int toMemberAge;
   final private LocalDateTime createdAt;
   
   public Follow(Long id, String fromMemberNickname, int fromMembeAge, String toMemberNickname, 
   int toMemberAge, LocalDateTime createdAt) {
      this.id = id;
      this.fromMemberNickname = fromMemberNickname;
      this.fromMembeAge = fromMembeAge;
      this.toMemberNickname = toMemberNickname;
      this.toMemberAge = toMemberAge;
      this.createdAt = createdAt;
   }
}

닉네임이 A라는 유저가 B 유저를 Follow 했을 때, Follow 객체는 new Follow(1, A, B, new LocalDateTime.now())와 같이 생성될 것이다.

위와 같이 Entity를 설계했을 때, Follow라는 데이터를 읽어오면 해당 데이터 내부에 필요한 데이터 전부가 들어있어 다른 데이터를 참조하지 않아 조회의 성능은 좋다.

하지만,  A라는 유저가 100만명을 Follow한 뒤, 닉네임을 변경하였다면 100만 개의 Follow 데이터의 fromMemberNickname 컬럼을 변경해주어야 하는 쓰기의 문제점이 발생한다.

 

Follow에 정규화를 적용하여, 다음과 같이 변경한다.

@Getter
public class Follow {
   final private long id;
   final private Long fromMemberId;
   final private Long toMemberId;
   final private LocalDateTime createdAt;
   
   public Follow(Long id, Long fromMemberId, Long toMemberId, LocalDateTime createdAt) {
      this.id = id;
      this.fromMemberId = fromMemberId;
      this.toMemberId = toMemberId;
      this.createdAt = createdAt;
   }
}

위와 같이 Entity를 설계한다면, Follow를 조회할 때, fromMember, toMember를 참조해야 해서 조회의 성능이 낮아진다.

하지만,  A라는 유저가 100만명을 Follow한 뒤, 닉네임을 변경하였다면 fromMember 데이터의 nickname 값 하나만 변경하면 되기 때문에 쓰기의 성능이 좋아진다.

 

만일, 애플케이션 특성상 유저의 닉네임을 변경할 수 없다면, 조회 시 다른 데이터를 참조하지 않아도 되고, 데이터의 변경 역시 없기 때문에, 정규화를 적용하지 않고 첫 번째 Follow 구조를 가져가는 것이 좋은 선택일 수 있다. 

* 테이블 설계 시, 중복된 데이터를 반드시 정규화하지 않고 데이터의 변경이 자주 발생하는 지 등의 여부를 판단하여 정규화, 반정규화를 잘 적용하는 것이 좋다.

 

정규화 시 고려해야 하는 것

  • 얼마나 빠르게 데이터의 최신성을 보장해야 하는지
  • 데이터의 변경 주기와 조회 주기
  • 테이블의 탐색 깊이가 얼마나 깊은지

'DB' 카테고리의 다른 글

[DB] 문자열 데이터 타입에 글자(한글) 수 제한하기  (0) 2023.07.29
[DB] MySQL  (0) 2022.12.08
[DB] MySQL vs PostgreSQL  (0) 2022.11.19
Hot Key  (0) 2022.11.09