> For the complete documentation index, see [llms.txt](https://guswns3371.gitbook.io/study/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guswns3371.gitbook.io/study/readme/db/undefined-1.md).

# 정규화

## 정규화

`정규화`란 “함수 종속성”을 이용하여 릴레이션을 연관성 있는 속성들로만 구성되도록 분해하는 과정

* 함수 종속성 : 릴레이션 속 어트리뷰트(속성)들 간의 연관성을 평가하기 위한 척도

> 정규화의 목표

정규화를 통해 이상 현상을 방지할 수 있다.

> 이상 현상

이상 현상(Anomaly)란 데이터베이스 내의 데이터가 중복되어 릴레이션 조작(삽입, 삭제, 갱신) 시 예상하지 못한 문제를 의미한다

1. `삽입 이상` : 의도하지 않는 데이터가 삽입되는 현상, 삽입 조건이 맞지 않아 삽입이 안 되는 현상

   ![Untitled](/files/283p88xdEE3eFukLrTXH)

   `melon(고객 아이디), 성원용(고객이름), gold(등급) 정보`를 삽입하고 싶지만 `이벤트 번호, 당첨여부` 속성은 NULL이 되면 안되기 때문에 삽입이 불가능함
2. `삭제 이상` : 원치 않은 정보까지 삭제되는 현상

   ![Untitled](/files/LUndDaA5v9JArest6TyG)

   아이디가 orange인 고객의 당첨여부 정보만 삭제하기 위해 튜플을 삭제 → 이벤트번호, 고객이름, 등급 정보까지 모두 삭제됨
3. `갱신 이상` : 일부 정보만 갱신되어 데이터 일관성이 깨지는 현상

   ![Untitled](/files/LqNiJtGDN3oPebSQXj3w)

   아이디가 apple인 고객의 등급을 vip로 갱신함 → 일부 튜플만 갱신되어 데이터 일관성이 깨짐

## 함수 종속성

`함수 종속성`이란 같은 릴레이션 속의 어트리뷰트가 함수적으로 다른 어트리뷰트를 결정하는 종속 관계이다.

```java
X(결정자) -> Y(종속자)
```

어트리뷰트 Y의 값이 어트리뷰트 X에 의해 결정될 때, 어트리뷰트 X와 Y는 함수 종속 관계를 가진다고 말한다.

* X : 결정자
* Y : 종속자

> 예시

![Untitled](/files/yeTZ9wnCdbFRLRp6Zuan)

![Untitled](/files/L8ta33bH9cCu6LAmXZSS)

`학번` 어트리뷰트는 `이름, 주소, 학년, 성별` 어트리뷰트 값들을 결정짓는다.

* `기본키, 후보키`는 다른 어트리뷰트들의 결정자가 될 수 있다.

> 완전 함수 종속

```java
{X, Y}(결정자) -> A(종속자)
X -/-> A
Y -/-> A
```

특정 어트리뷰트(`A`)는 둘 이상의 어트리뷰트 조합(`{X, Y}`)의 종속자이지만, 결정자의 일부 어트리뷰트(`X 또는 Y`)에는 종속자가 아닌 경우이다.

> 부분 함수 종속

```java
{X, Y}(결정자) -> A(종속자)
X(결정자) -> A(종속자)
Y(결정자) -> A(종속자)
```

특정 어트리뷰트(`A`)는 둘 이상의 어트리뷰트 조합(`{X, Y}`)의 종속자이고, 결정자의 일부 어트리뷰트(`X 또는 Y`)에도 종속자인 경우이다.

> 이행적 함수 종속

```java
X(결정자) -> Y(종속자)
Y(결정자) -> Z(종속자)

X(결정자) -> Z(종속자)
```

어트리뷰트X가 Y의 결정자이고, Y가 Z의 결정자라면 X가 Z의 결정자가 된다.

## 정규화 단계

![Untitled](/files/I9KbrkpO0X1O3N98rNg1)

1차 정규화에서 n차 정규화까지 진행하면서 데이터베이스의 바람직하지 않은 구조를 개선해 나간다.

* 보통 3차 정규화까지만 해도 충분하다고 한다.
* 실무에선 비용의 문제로 정규화를 안하는 경우가 있다. (릴레이션 간의 join 연산이 증가하여 질의 응답 시간이 늘어날 수 있기 때문)

### `🧩제 1 정규화`

* `릴레이션의 모든 어트리뷰트가 원자값을 가져야 한다.`
* `동일한 성격의 어트리뷰트가 여러개 존재하면 안된다.`

![Untitled](/files/vupTxLxPbSo7GIhvblVk)

![수강과목1, 수강과목2 처럼 동일한 성격의 어트리뷰트가 존재하면 안된다.](/files/sisaQNdTiYip0Stv7hXS)

수강과목1, 수강과목2 처럼 동일한 성격의 어트리뷰트가 존재하면 안된다.

📎 제 1 정규화를 해도 \`부분 함수 종속 관계\`가 존재하기 때문에 삽입, 삭제, 갱신 이상현상이 발생한다.

![Untitled](/files/rk8628QlWJR7D2I6XAjf)

```java
{고객아이디, 이벤트번호}(결정자)→ 당첨여부(종속자)
고객아이디 -/→ 당첨여부
이벤트번호 -/→ 당첨여부
```

### `🧩제 2 정규화`

* `제 1 정규형에 속하면서`
* `기본키가 아닌 모든 어트리뷰트들이 기본키에 완전 함수 종속된다`

![Untitled](/files/3STGUUj0MD42jk2yJYg3)

📎 제 2 정규화를 해도 \`이행적 함수 종속 관계\`가 존재한다.

![Untitled](/files/JC7NdPDxVcavkVukxLnQ)

```java
고객아이디(결) -> 등급(종)
등급(결) -> 할인율(종)

고객아이디(결) -> 등급 -> 할인율(종)
```

### `🧩제 3 정규화`

* `제 2 정규형에 속하면서`
* `기본키가 아닌 모든 어트리뷰트들이 기본키에 이행적 함수 종속이 없어야 한다`

![Untitled](/files/gC8t4MZMg3BLmcxm5UO6)

### `🧩BCNF(Boyce-Codd) 정규화`

* `제 3 정규형을 강화한 버전`
* `제 3 정규형을 만족하면서 모든 결정자가 후보키 집합에 속해있어야 한다`

> 제 3 정규형을 만족하지만 BCNF 정규형을 만족하지 않는 경우

![Untitled](/files/yPq06iJCx7zpi420Y6aT)

```java
후보키 = {학생, 과목}

{학생, 과목}(결정자) -> 교수(종속자)
{학생, 과목}(결정자) -> 학점(종속자)

교수(결정자) -> 과목(종속자) // BCNF 정규형에 속하지 않음
```

후보키 집합은 `{학생, 과목}`이다. 하지만 후보키가 아닌 `교수` 어트리뷰트가 `과목` 어트리뷰트의 결정자 역할을 하고 있기 때문에 BCNF 정규형에 속하지 않는다.

> BCNF 정규화를 해보자

![Untitled](/files/4scRRTpCQYMrkW93I3XL)

## 반정규화

`반정규화`란 정규화를 진행한 릴레이션을 필요에 의해 다시 합치는 과정이다.

* 정규화를 진행하면 릴레이션이 분리된다 → JOIN 연산이 많아져 쿼리 응답시간이 길어지는 문제가 발생한다.
* 데이터 중복을 허용하면서 JOIN 연산을 줄이기 위해 반정규화를 진행한다

> 반정규화가 필요한 경우

* 데이터 조회시 JOIN 연산이 지나치게 많이 수행되는 경우
* 특정 데이터 또는 특정 범위만 자주 조회하는 경우
* 정규화를 진행하였지만 쿼리 응답 속도가 느린경우
* 요약, 집계 정보가 자주 요구되는 경우

> 정규화와 반정규화는 Trade-Off 관계

|              | 정규화      | 반정규화     |
| ------------ | -------- | -------- |
| 데이터 정합성, 일관성 | 높아진다     | 낮아진다     |
| 이상 현상        | 덜 발생     | 자주 발생    |
| 쿼리 성능        | 나빠질 수 있음 | 좋아질 수 있음 |
