정규화(Normalization)
- 데이터베이스의 테이블이 잘 만들어졌는지 평가하고, 잘 만들지 못한 테이블을 고쳐나가는 과정.
- 데이블을 정규형(normal form) 이라고 불리는 형태에 부합하게 만들어나가는 과정.
- 정규형(normal form) : 1NF,2NF,3NF.../ 순서에 따라 규칙이 누적된다.
- 데이터베이스에서 삽입,업데이트,삭제 이상을 없앨 수 있다.
- 새로운 종류의 데이터를 추가할 때 테이블 구조 수정을 많이 하지 않아도 된다.
- 데이터베이스 구조를 단순화해서 사용자가 더 쉽게 이해할 수 있다.
- 데이터 모델을 만들고, 데이터베이스에 구현하기 전에 적용하면 좋다.
정규화 단계
모든 릴레이션이 제 5 정규형에 속해야 되는 것은 아니다. 릴레이션 특성을 고려하여 적합한 정규형을 선택하면 된다.
일반적으로 제 1/2/3//BCNF형 정규형(기본 정규형)에 속하도록 정규화하는 경우가 대부분이므로 기본 정규형의 제약조건을 정확히 파악해둘 필요가 있다.
1NF
테이블 안 모든 row의 모든 column값들은 나눌 수 없는 단일 값이어야 한다.
id | name | phone | |
1 | yoon@~.com | 융디 | 010-456-789,010-123-456 |
2 | ga@~.com | 가디 | 011-123-456,011-987-456 |
3 | na@~.com | 나디 | 011-321-987 |
4 | da@~.com | 다디 | 010-666-666,010-951-453 |
여기서 phone은 제 1 정규형에 부합하지 않는다. 한 컬럼에 정보가 많이 들어가 있기 때문에 수정과 조회가 어렵다.
이를 해결하기 위해서는 phone테이블을 따로 나눠서 여러 개의 전화번호를 저장하고, uesr테이블도 나눠 user_id를 foregin key로 사용해서 각 전화번로가 어떤 유저의 전화번호인지를 나타내면 된다.
정리
- 한 컬럼에 같은 종류의 값을 여러 개 저장하고 있을때는 해당 컬럼을 하나의 테이블로 분리해서 모델링한다.
- 한 컬럼에 서로 다른 종류의 값을 여러 개 저장하고 있을 때 한 컬럼을 여러 개로 분이해서 모델링한다.
함수 종속성(Funtional Dependency)
테이블 안 attribute들 사이에서 생기는 관계를 말한다.
예를들어
테이블 A에 attribute x가 있다고 하자, 이때 x의 값에 따라서 y의 값이 결정될 때, y는 x에 함수 종속성이 있다고 말한다.
name | age | phone | |
융디 | yoon@~.com | 20 | 010-456-789 |
가디 | ga@~.com | 22 | 011-123-456 |
나디 | na@~.com | 24 | 011-321-987 |
다디 | da@~.com | 26 | 010-666-666 |
이 테이블에서 name을 알면 그 name에 해당하는 사람의 이메일,나이, 휴대전화번호를 알 수 있다.
이때 emali, age, phone은 name에 함수 종속성이 있다라고 하는 것이다.
함수 종속성은 반드시 하나의 컬럼에만 있어야 하는 것은 아니다.
예를 들어 , a유저가 b상품에 대한 c점수를 주었을 때 c점수는 a유저와 b상품에 함수 종속성이 있다고 한다.
이행적 함수 종속
그림에서 확인할 수 있듯이 할인율 속성은 기본키인 고객아이디에 함수적으로 종속됨과 동시에 등급을 통해서 고객아이디에 이행적 함수 종속된다. 이러한 이행적 함수 종속이 나타나는 이유는 함수 종속 관계가 하나의 릴레이션에 여러 개 존재하기 때문이다.
고객아이디 -> 등급 을 알 수 있고, 등급-> 할인율을 알 수 있다.
등급에 따라 결정되는 할인율이 고객아이디 속성과 함께 세 가지 속성들이 하나의 릴레이션에 속하게 되니, 고객 아이디가 할인율을 결정하게 되는 것처럼 관계가 형성된다. 그리고 이로 인해 이상 현상이 발생하게 된 것이다(마치 기본키에 종속된 관계가 두 개처럼 보여짐).
2NF
- 1NF에 부합해야 한다.(테이블 안 모든 값이 나눌 수 없는 단일 값이어야 한다.)
- 테이블에 candidate key의 일부분에 대해서만 함수 종속성이 있는 non-prime attribue가 없어야 한다.
id | user_id | product_id | age | price | score | comment |
1 | 5 | 4 | 22 | 5000 | 5 | 좋아요 |
2 | 16 | 6 | 26 | 12000 | 3 | 사기당함 |
3 | 7 | 11 | 25 | 15000 | 4 | 휘뚜루마뚜루 |
4 | 2 | 18 | 36 | 10000 | 5 | 만족만족 |
review는 하나의 유저가 하나의 product에 주는 평가이기 때문에 user_id와 product_id만 있으면 하나의 review row를 특정 지을 수 있다.
여기서 {user_id,product_id} = candidate key이다.
age와 price는 row를 특정 지을 수 없기 때문에 non-prime attribute이다.
age는 user_id, price는 product_id에 대해서 함수 종속성이 있다. 이는 {user_id,product_id} 의 전체에 대한 함수 종속성이 아니고,
일부에 대해서만 의존하기 때문에 제 2정규형에 부합하지 않는다.
이를 해결 하기 위해서는 user / product / review 테이블을 따로 만들어 주면 된다.
3NF
- 2NF에 부합해야 한다.
- 테이블 안에 있는 모든 attribute들은 오직 primary key에 대해서만 함수 종속성이 있어야 한다.(테이블의 모든 attribute는 직접적으로 테이블 Entity에 대한 내용이어야만 한다.)
- 이행적 함수 종속성도 있으면 안된다.
id | name | brand_id | price | designer | designer_nation |
1 | 애디대수 | 1 | 200만원 | 곽필유 | 대한민국 |
2 | 노이퀴 | 2 | 300만원 | 다니엘 스미스 | 미국 |
위 테이블은 name, brand_id, price, designer, 모두 한 상품에 대한 내용이다.
직접적으로 id에 대한 함수 종속성이 있다. 하지만 디자이너 국적은 직접적으로는 어떤 상품인지가 아니라, 어떤 디자이너인지에 따라 결정되는 값이다. 이행적 함수 종속성을 가지고 있다.
하나의 상품은 하나의 디자이너만 있을 수 있고, 한 명의 디자이너는 여러 제품을 디자인할 수 있다.
디자이너와 상품은 1:N 관계가 있다. 다수에 해당하는 product 테이블에 foreign key를 넣어줘서 관계를 모델링하면 된다.
비정규화
정규형에 부합하는 테이블을 정규형을 지키지 않게 바꾸는 걸 의미한다.
다양한 정규형은 테이블이, 좋은지, 안 좋은지 판단할 수 있는 일종의 기준이라고 했는데, 왜 더 안 좋게 만들까하냐면
바로 성능 개선을 위해서입니다.
정규형을 지키기 위한 가장 기본적인 해법은 하나의 테이블을 여러 개로 나누는 것이다.
그렇기 때문에 데이터베이스에서 원하는 데이터를 찾을 때는 조인(join)을 사용해서 다양한 테이블들에 있는 데이터를 합쳐야 하는 경우가 많다.
정규화로 인해서 데이터가 이곳저곳 너무 많이 퍼져있으면, 퍼져있는 데이터를 다시 모을 때 속도가 느려질 수 있다.
비정규화를 하면 이런 정보들은 한 테이블에 저장할 수 있기 때문에 조금 더 빠르게 조회를 할 수 있다.
하지만 비정규화를 고려할 때는 항상 삽입, 업데이트, 삭제 이상 현상에 대한 문제점들에 대해서 인지하고 있어야하며,
- 데이터가 너무 퍼져있어서 조회 연산의 성능 문제가 심각한 수준으로 일어나는 게 확실하고
- 테이블을 삽입, 업데이트, 삭제하는 것보다 조회하는 용도로만 사용하고 있을 때
이 두 경우에만 고려할 수 있다.
'DataBase' 카테고리의 다른 글
[SQLD] 데이터모델링(Data Modeling) (0) | 2023.03.07 |
---|---|
[SQL] 집계 함수(Aggregate function )/ 기본 함수와 연산 (0) | 2023.03.04 |
[SQL] LIKE 와일드카드 (0) | 2023.03.03 |
[SQL] WHERE절 (0) | 2023.03.03 |
[SQL] SQL (Structured Query Language) (0) | 2023.03.03 |
댓글