비정규화는 언제 사용되나?

- 5 mins

“정규화”, “비정규화”란 용어는 데이터베이스 설계에서 자주 접하게 되는 개념이다. 정규화는 테이블 간 데이터의 중복을 최소화하는 것을 목표로 하며, 이를 통해 데이터 무결성을 유지한다. 반면, 비정규화는 성능 향상, 데이터 검색 속도 증가를 위해 중복, 통합, 분할하는 과정이다.

일반적으로 데이터베이스를 설계할 때, 대부분 정규화를 기본으로 한다. 그리고 그것이 당연하다고 생각했었고 그 외엔 생각하지 못했다. 그러던 중, 한 질문을 받게 되었는데.

비정규화를 사용할 때는 언제인거 같아요?

이 질문은 전혀 생각해보지 못했던 질문이었다. 데이터의 중복을 허용할 때는 언제인걸까? 성능을 더 고려해야 하므로 조인을 줄일 때? 그러면 데이터 중복으로 인해서 수정시 성능 하락이 있지 않을까? 그럼에도 사용할 때가 언제인걸까?

비정규화의 장단점

비정규화는, 앞서 언급했듯이, 데이터 중복을 허용하는 기술이다. 예를 들어, “주문”, “고객” 테이블이 있다고 해보자.

주문 내역과 고객의 이름이 동시에 필요한 상황이라면, 일반적으로는 ‘고객’ 테이블에서 정보를 가져오기 위해 ‘주문’ 테이블과 조인을 수행한다. 이런 조인을 줄이기 위해 ‘주문’ 테이블에 ‘고객 이름’이라는 칼럼을 추가할 수 있다.

이렇게 하면 조회 속도가 빨라질 것이다. 그러나 만약 고객이 이름을 자주 바꾼다면 어떻게 될까?

“고객” 테이블만 수정하는 것이 아니라, “주문” 테이블도 수정해야 할것이다. 이 예시는 단순히 두 개의 테이블에만 해당하지만, 중복이 많은 테이블에서는 이런 문제가 장애로 이어질 수 있다.

denormalization1

출처: https://www.splunk.com/en_us/blog/learn/data-denormalization.html

비정규화의 장점

비정규화의 단점


비정규화 기술들

비정규화를 하는 방법은 하나만이 아니다. 여러가지 상황이 있고 거기에 맞게 사용할 수 있는 방법들이 있다.

파생되는 값이 자주 사용될 경우

쿼생쿼리 실행 중에 반복적으로 계산이 필요한 경우가 있다. 예를 들어, 학생 테이블의 국어, 영어, 수학 점수가 들어있는 테이블이 있다고 해보자.

학생 국어 영어 수학
A 90 80 70
B 80 70 60
C 70 60 50

그런데 선생님이 필요한 값은 학생들의 총점이나 평균이다. 그래서 쿼리를 조회할 때마다 평균 값과 총점을 계산한다. 이때 평균 값과 총점은 파생되는 값이고 자주 사용된다. 비정규화를 통해 같이 저장해보자.

학생 국어 영어 수학 총점 평균
A 90 80 70 240 80
B 80 70 60 210 70
C 70 60 50 180 60

테이블 사전 조인

테이블을 사전 조인이란, 비즈니스 가치가 없는 테이블에 열을 추가한다. 예를 들어, 카테고리 별로 모든 사용자의 메시지를 조회한다고 해보자. 이때 조인을 줄이기 위해 User_messages 테이블에 category_name 칼럼을 추가한다.

이제 User_messages의 테이블만 조회하면 카테고리별로 분류가 가능해진다. 주의할 점은 카테고리의 이름이 변경되면 User_messages의 칼럼의 이름도 변경해야 한다.

denormalization2

출처: https://rubygarage.org/blog/database-denormalization-with-examples

첨부파일이 여러 개일 때

보통 사용자가 첨부파일을 여러 개 첨부할 때, ‘뻐꾸기 외 3개’처럼 제일 첫 번째 파일 이름만 필요할 때가 있다. 이때 제일 첫 번재 이름만 마스터 테이블에 포함시킨다. 역시나 주의할 점은 파일이 수정될 때, 마스터의 첫 번째 첨부 파일 이름 칼럼도 수정되어야 한다.

denormalization3

테이블 분할

테이블 분할은 큰 테이블을 조금 더 쉽게 쿼리하고 관리할 수 있도록 여러 개의 작은 테이블로 분해하는 프로세스이다. 파티션과는 조금 다르다.

수평 테이블 분할

수평 테이블 분할이란, 특정 조건에 따라서 을 여러 개의 작은 테이블로 나누는 것의 의미한다. 예를 들어, “고객” 테이블을 가지고 있다고 해보자. 이 테이블은 고객 ID, 이름, 이메일, 거주 지역이 포함된다.

고객이 점차 많아짐에 따라 혹은 요구사항을 위해 거주 지역별로 테이블을 분할하기로 결정했다고 해보자.

고객ID 이름 이메일 거주지
1 김철수 철수@example.com 서울
2 이영희 영희@example.com 부산
3 박지성 지성@example.com 서울
4 최수지 수지@example.com 부산

서울에 거주하는 고객

고객ID 이름 이메일 거주지
1 김철수 철수@example.com 서울
3 박지성 지성@example.com 서울

부산에 거주하는 고객

고객ID 이름 이메일 거주지
2 이영희 영희@example.com 부산
4 최수지 수지@example.com 부산

이렇게 데이터를 분할하면, 특정 지역에 대한 고객 정보를 더 빠르게 검색하고 관리할 수 있게 된다. 단, 전체 고객 데이터를 조회하거나 조인할 때는 성능이 저하될 수 있다. 이때는 뷰를 생성하여 관리하자.

수직 테이블 분할

수직 테이블 분할은 테이블의 을 분할하는 방법이다. 테이블마다 자주 사용되는 칼럼이 있고 반대도 있을것이다. 이때 사용할 수 있는 방법인데. 예를 들어, “사원” 테이블을 가지고 있다고 해보자.

이 테이블에는 사원 ID, 이름, 직무, 이메일이 포함되어 있다. 그런데 사원의 기본 정보만 필요하고 불필요한 이메일 정보는 필요하지 않다고 해보자. 이때 열을 기준으로 테이블을 분할한다.

사원ID 이름 직무 이메일
1 김철수 개발자 철수@example.com
2 이영희 디자이너 영희@example.com
3 박지성 개발자 지성@example.com
4 최수지 디자이너 수지@example.com

사원 기본 정보

사원ID 이름
1 김철수
2 이영희
3 박지성
4 최수지

사원 이메일 정보

사원ID 이메일
1 철수@example.com
2 영희@example.com
3 지성@example.com
4 수지@example.com

비정규화를 언제해야 할까?

정규화는 데이터베이스 설계의 핵심 원칙 중 하나이다. 그 이유는 DRY(Don’t Repeat Yourself) 원칙에 따라 중복된 데이터를 피하는 것이 문제를 발생시키는 것을 방지하기 때문이다. 그러나 특정 경우에는 비정규화가 필요할 수 있다.

비정규화를 고려하기 전에 먼저 검토해야 할 몇 가지 핵심 질문이 있다.

특히, 데이터가 자주 변경되지 않고, 보고서 제출용이 아닌 경우라면, 비정규화가 필요한지 꼼꼼하게 살펴보는 것이 중요하다. 다양한 자료를 통해 얻은 지식으로 보아, 비정규화는 반드시 필요한 경우에만 적용해야 함을 알 수 있었다.




참고 :

https://guides.visual-paradigm.com/balancing-data-integrity-and-performance-normalization-vs-denormalization-in-database-design/

https://www.analyticsvidhya.com/blog/2022/08/database-normalization-a-step-by-step-guide-with-examples/

https://www.splunk.com/en_us/blog/learn/data-denormalization.html

https://rubygarage.org/blog/database-denormalization-with-examples

Gyuhwan Sim

Gyuhwan Sim

배움과 실천의 즐거움

comments powered by Disqus