🟨 목 차 🟨
1. 정규화 란 ?
1-1. 데이터베이스 정규화 절차
1-2. 제 1차 정규화
1-3. 제 2차 정규화
1-4. 제 3차 정규화
1-5. 정규화 정리
2. 역정규화 란 ?
2-1. JOIN[컬럼 중복] 을 줄이는 역정규화
2-2. 계산작업[파생 컬럼의 형성] 을 줄이는 역정규화
2-3. 테이블 분리를 하는 역정규화
2-4. 외래키를 줄이는 역정규화
지난 시간에 ERD 다이어그램에 대해서 배워보았습니다.
ERD 다이어그램을 설계하는 과정중에 효율적이지 못한 모델링을 만들었습니다. 이것을 해결하기 위해서는 정규화 과정이 필요합니다.
정규화에 대해 알아봅시다 :)
◼️ 1. 정규화 란 ? ◼️
ERD 내에서 중복요소를 찾아 제거해 나가는 과정
[ 중복된 데이터는 많은 문제를 일으키기 때문 ]
많은 정규화 정도가 있지만 3차 정규화 정도만 알면 설계하는데 무리가 없다.
==> 중복을 최소화 [ 완전히 중복을 없애는게 아니라 어느정도는 인정하겠음 ] , 시간을 줄이기 위해 [ 데이터베이스 안에 몇 억개의 튜플이 있다고 생각하면 쉽다 ]
몇가지 원칙만 지킨다면 정규화가 필요없는 ERD를 설계 할 수 있다.
◼️ 1-1. 데이터베이스 정규화 절차
함수 종속성을 이용하여 릴레이션을 연관성이 있는 속성들로만 구성되도록 분해해서 이상현상이 발생하지 않도록 단계별 접근
[ 기본 정규형으로는 제 1·2·3·보이스/코드 정규형이 있으며, 제 4·5 정규형은 고급 정규형으로 분류 ]
◼️ 1-2. 제 1차 정규화
제 1차 정규화는 같은 성격과 내용의 컬럼이 연속적으로 나타나는 컬럼이 존재할 때, 해당 컬럼을 제거하고 기본테이블의 PK를 추가해 새로운 테이블을 생성하고, 기존의 테이블과 1:N 관계를 형성하는 것
위에 사진을 보게 되면,
Unnormalized form테이블의 tag 필드를 보면, 값들이 여러 개가 들어가 있다.
==> 하나의 필드에 값들이 여러개 있으면 안된다.
이것들을 정규화를 시켜보면
- 우선 하나의 title은 여러개의 tag를 같는다. 또한 tag(예를 들어 rdb)는 여러개의 title(mySQL, Oracle)을 가진다.
- 그러면 title과 tag를 테이블 두 개로 분리했을 때 이들의 관계는 M:N이 된다.
- M:N을 표현하기 위해선 테이블 3개를 만들어야 한다.
- topic테이블에서 tag를 분리 시키기 위해 title과 tag의 필드(이것은 순차 번호로 새로 만들어야함)를 포함하는 topic_tag_relation 테이블을 만들고 완전한 관계를 위해서 그 tag의 순차번호와 이름을 통해 tag테이블을 만들어 완전한 M:N 관계를 만든다.
- 각각의 테이블에 1:N 관계를 연결해주면 정규화가 완료된다.
[Ex]
◼️ 1-3. 제 2차 정규화
제 2 정규화는 PK가 여러키로 구성된 복합키(Composite Primary Key)로 구성된 경우가 2차 정규화 대상이 되며, 복합키 전체에 의존하지 않고 복합키의 일부분에만 종속되는 속성들이 존재할 경우(부분적 함수 종속 관계) 이를 분리 하는 것이다.
위에 사진을 보며,
- 제 1정규화를 마친 테이블을 보게되면, 중복되는 레코드(적갈색)가 보인다.
- 저 부분이 중복되어 나타는 이유는 type와 price 필드 값이 각각 다르기 때문이다.
- 그러면 각기 다른 부분을 테이블로 나누고 중복되는 부분을 하나로 표현되게 해야한다.
- 먼저 중복이 나타나게 한 원인 필드인 type와 price 필드를 따로 빼서 topic_type 테이블을 만든다.
- 그리고 난 후 topic_type에서 식별할 수 있는 외래키 title을 등록해준다.
- 이렇게 하게 되면, 중복되는 것 없이 title이 MySQL이냐 ORACLE이냐에 따라 topic 테이블에선 저자정보를 알 수 있으며, topic_type 테이블에선 타입과 가격을 각각 알 수 있다.(=중복없이)
◼️ 1-4. 제 3차 정규화
테이블의 키가 아닌 컬럼들은 기본키에 의존해야 하는데 겉으로는 그런 것 처럼 보이지만 실제로는 기본키가 아닌 다른 일반 컬럼에 의존하는 컬럼들이 있을 수 있다. 이것들은 이전적 함수 종속 관계라고 한다.
즉, 제 3정규화는 PK에 의존하지 않고 일반컬럼에 의존하는 컬럼들을 분리한다.
위에 사진을 보며,
- 제 2정규화를 마쳤지만 여전히 중복된 값(노란색)이 보이게 된다.
- 저 레코드는 author_id에 의존하는 컬럼들이다. 대충보면 title에 의존하는 것 처럼 보이지만 아니다.
- 그러면 PK(title)에 의존하지 않은 컬럼들을 분단시켜야 한다.
- author라는 테이블을 만들고 중복되는 컬럼들 3개를 그대로 따온다. 그리고 totpic 테이블의 author_id로 외래키 관계를 맺어준다. 그러면 중복이 사라진다.
만약 autho_id가 없고 author_name, author_profile만 있다고 가정하게 되면,
여전히 중복이 나타난다. 그렇기에 저 중복된 컬럼들을 따로 빼고, PK를 왜래키로 가져오거나 아니면 구분할 수 있는 새로운 컬럼을 만들어서 위와 같이 연결해주는 것도 나쁘지 않다.
◼️ 1-5. 정규화 정리
정규화 과정이란, 중복된 속성을 최소화 하고 종속관계에 있는 속성을 제거하는 과정이다.
이러한 정규화 과정을 다시 조인하면 데이터의 손실 없이 이전상태로 복구가 가능해야 한다.
◼️ 2. 역정규화 란 ? ◼️
논리적 정규화를 통해 만든 표를, 개발적 측면에서 성능이나 편의성을 위해 되돌아 가는 작업
[ 이 말 때문에 정규화를 한다고 해서 반드시 성능을 떨어뜨리는 것이 아니기 때문에 오해 하지 말도록. ]
위와 같은 정규화를 마친 논리적 테이블들이 있다고 하자.
◼️ 2-1. JOIN[컬럼 중복] 을 줄이는 역정규화
위의 사진은 정규화를 마친 논리적 테이블을 JOIN을 줄이기 위한 역정규화(되돌아 가는작업)을 한 것이다.
- 만일 topic_tag_relation의 topic_title 필드를 가지고 tagName을 알아야 한다고 가정해보자.
- 그러면 topic_tag_relation과 tag테이블을 조인해서 조건에 부합하는 name컬럼 값을 가져오면 된다.
- 하지만 만일 저러한 쿼리가 서버내에서 많이 일어날 경우, join은 많은 부하가 일어날 것이다.
- join의 대책으로 그냥 테이블을 하나로 합쳐버리는것이다.
- 즉, 제 1정규화를 통해 나눴던 것을 성능과 편의를 위해서 역으로 돌아가버린 것(역정규화)이다.
◼️ 2-2. 계산작업[파생 컬럼의 형성] 을 줄이는 역정규화
위의 사진은 데이터를 처리하는 비용을 줄이기 위한 역정규화(되돌아 가는작업)을 한 것이다.
- 만일 count 값이 필요하다고 가정하자. 쉽게 group by를 통해 컬럼을 묶고 조회하면 된다.
- 하지만 이러한 쿼리가 빈번하게 일어난다면 부하가 일어난다.
- 따라서 그룹핑을 해서 내장함수를 쓰는게 아니라 아예 topic_count데이터 필드를 추가하여 데이터를 주는것이다.
- 하지만 유효한 데이터를 유지하기 위해서는 글이 추가될때마다 지속적으로 데이터를 업데이트해야 하는 관리를 해야한다.
[트리거를 쓴다던가 서버 사이드에서 처리하면 된다고 한다.. 아직 이 부분은 잘 모르겠다.] - 중요한 것은 count값을 이용할때 group by 방법이 아닌 효율적으로 부하를 줄이는 방법을 찾는것이다.
◼️ 2-3. 테이블 분리를 하는 역정규화
하나의 표를 성능을 위해서 여러개로 쪼개는 경우이다.
만일 topic테이블에 description의 용량이 엄청많을경우인데, topic 테이블을 자주 조회했을 경우에 부하가 올 수 있따.
그래서 표의 성능을 위해 용량이 큰 테이블을 따로 분리하는 것이다.
==> 테이블을 나누면 여러대의 서버에서 각기 다르게 접근해서 성능이 좋기 때문이다.
행을 기준으로 분리하는 것은,
만일 author_id 회원이 몇 만명일 경우 하나의 테이블에 접근해서 처리하는것보다, 테이블을 분담해서 author_id가 1000이하일 경우 1500 이상일 경우 각기 다른 테이블로 접근해서 부하를 줄이는것이다.
==> 이것을 MySQL에서 파티션 기법이라고 한다. 쉽게 말해 데이터 값이 클 때 원하는대로 잘라서 각기 다른 테이블을 접근 하는 것이다.
◼️ 2-4. 외래키를 줄이는 역정규화
join을 줄여서 지름길을 만드는 테크닉이다.
처음에 배웠던 JOIN[컬럼 중복] 을 줄이는 역정규화 방법에서 외래키를 통해서 줄이는 방법이라 보면 된다.
어느 저자의 태그아이디와 태그명을 조회한다고 가정 했을때,
우리는 세가지 필드 어느 저자인지(author_id) tag_id, tag_id, tag테이블의 Name이 필요하다.
이들을 조회하기 위해선 3개의 테이블을 join하고 불러오면 되지만, join을 많이 쓰면 성능이 안 좋아진다.
==> 그래서 topic_tag_relation 테이블에 author_id 컬럼을 추가하면, join을 한번만 하면 원하는 결과를 얻을 수 있다.
참고
'DB > MySQL' 카테고리의 다른 글
DB ERD 다이어그램 (0) | 2022.08.22 |
---|---|
DB Key의 종류 (0) | 2022.08.21 |
My SQL 테이블 제약 조건 feat.Workbench (0) | 2022.08.21 |
MySQL 테이블에서 원하는 데이터 쉽고 빠르게 찾기(INDEX) feat.Workbench (0) | 2022.08.20 |
MySQL 다른 쿼리 내부에 포함되어 있는 SELECT문(서브쿼리) feat.Workbench (0) | 2022.08.20 |