DB 테이블 설계를 잘못하면 무슨 문제가 생길까?

김민우·2022년 10월 13일
0

TIL

목록 보기
4/10

DB schema 설계를 잘못하면 어떤 문제가 생길까?

바로, 이상 현상(Anomaly)이 생기는 것이다.
이상 현상은 삽입 이상(Insertion Anomaly), 삭제 이상(Deletion Anomaly), 갱신 이상(Modification or Update Anomaly), 으로 구성된다.

하나하나 살펴보자.

- Anomaly

1. Insertion anomaly

예를 들어, IT 회사의 DB를 구축하는데 다음과 같은 테이블을 만들었다고 가정해보자.

EMPLOYEE_DEPARTMENT

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id

임직원 정보와 부서 정보를 하나의 테이블에 저장할 수 있도록 설계를 한 예시이다. (empl_id가 primary key이다.)

이때, 데이터를 write (insert, update, delete) 하게 되면 어떤 문제가 생길까?
먼저 데이터를 추가할 때, insertion anomalies가 발생하게 된다.

예를 들어, 임직원 정보를 하나 추가한다고 가정해보자.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1

이렇게 SUNGGON이라는 임직원을 하나 추가할 때는 문제가 없다.

데이터를 하나 더 추가해보자.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1

MINWOO라는 임직원을 한명 더 추가했다.

여기서, 부서(dept) 파트를 살펴보자.

이 부분은 중복 데이터가 된다.
부서의 아이디(1001), 부서 이름(DEV), 부서 리더의 아이디(1) 가 같은, DEV팀의 데이터가 중복으로 발생한다.

이러한 중복 데이터는 다음과 같은 문제점이 있다.

  • 저장 공간이 낭비된다.
  • 실수로 인한 데이터 불일치가 발생할 가능성이 생긴다.
    - 만약, 둘 중 하나의 dept_nameDEB라고 작성한다면 같은 데이터임에도 불구하고 데이터 불일치가 발생할 수도 있는 것이다.

그래서 가능하다면 중복 데이터는 최대한 줄이는 것이 좋다.

이어서, 만약 아직 부서 배치를 받지 못한 직원을 추가하게 된다면 어떻게 될까?

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........???

아직 부서 배치를 못받은 SEHOON이라는 직원이 들어왔다.
?값에는 어떤 값들이 들어가야 할까?
부서와 관련된 attribute가 있음에도 불구하고 저기에는 일단 null 데이터를 넣어야 한다.
그러나, null값을 많이 쓰는 것은 좋은 것이 아니다. 즉, 가능한 null 값은 적게 쓰는 것이 좋다.

이어서, 또 다른 데이터를 추가해보자.
그러나 이번에 넣을 데이터는 임직원이 한 명도 없는 부서 정보만 입력하는 것이다.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON..........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........nullnullnull
4????1002QAnull

QA팀의 아이디, 이름이 입력 되었지만, 소속된 임직원이 아무도 없기에 리더의 아이디가 없다.
또한, 소속된 임직원이 없기에 ?에는 null값이 입력된다.
이때, empl_id는 primary key이기에 null값을 가질 수 없기에 임시로 4라는 값을 넣어주게 된다.

이 상황에서, QA팀에 첫 직원이 들어왔다고 해보자.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........nullnullnull
4????1002QAnull
5HYUNJIN......50001002QA5

QA팀에 HYUNJIN이라는 첫 직원이 들어왔다. (그렇게 현진은 리더가 된다.)

이제 부서 정보를 저장하기 위해 임시로 넣어뒀던 4번 row의 정보는 삭제를 해야하는 번거로움이 발생한다.

왜 이러한 문제가 발생했을까?
두 개의 관심사 (임직원 정보와 부서 정보)를 한 테이블에서 관리하려고 했기 때문이다. 즉, 별개의 관심사가 한 테이블에 있는 것이 원인이다.

그렇다면, 어떻게 해결해야 할까?

테이블을 설계할 때는 관련있는 하나의 관심사만 묶어서 테이블로 설계하는 것이 바람직한 방법이다.

각각에 대한 것을 따로 테이블로 만들어주면 다음과 같이 설계할 수 있다.

<EMPLOYEE>

empl_idempl_namebirth_datepositionsalarydept_id
1SUNGGON.........1001
2MINWOO.........1001
3SEHOON.........null
5HYUNJIN......50001002

<DEPARTMENT>

dept_iddept_namedept_leader_id
1001DEV1
1002QA5

임직원 테이블은 empl_id가 primary key가 되고, 부서 테이블은 dept_id가 primary key가 된다.

임직원 테이블에 있는 dept_id는 부서 테이블의 dept_id를 레퍼런스하는 외래 키(foreign key)가 된다.

여기서 새로운 임직원을 추가해보자.

empl_idempl_namebirth_datepositionsalarydept_id
1SUNGGON.........1001
2MINWOO.........1001
3SEHOON.........null
5HYUNJIN......50001002
6CHANIK.........?

CHANIK이라는 새로운 임직원을 추가 했을 때, 임직원 테이블에 추가를 하면 된다.
CHANIK이라는 직원이 아직 부서를 배정받지 못했을 경우, dept_idNULL값을 주면 되는 것이고, 만약 DEV팀이라면 1001이라는 값을 넣어주면 되는 것이다.

추가적으로, 새로운 부서 정보를 입력하게 된다면 어떻게 될까?
다음 표와 같이 부서 테이블에만 새로운 데이터를 추가하면 되는 것이다.

dept_iddept_namedept_leader_id
1001DEV1
1002QA5
1003DESIGNNULL

이러한 방식으로 테이블을 잘 설계한다면 중복된 데이터를 줄일 수 있고 NULL 값도 적게 쓰게 되며 훨씬 더 깔끔하게 데이터를 다룰 수 있다.

2. Deletion anomaly

다시 이전의 개떡같은 스키마를 보자.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........nullnullnull
5HYUNJIN......50001002QA5

이 테이블에서 HYUNJIN의 정보(tuple)를 삭제하면 어떻게 될까?

현재, HYUNJIN은 QA 팀에 사수도 부사수도 없는 최후의 1인이다.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........nullnullnull

HYUNJIN의 정보를 삭제하게 된다면 QA 팀에 대한 데이터 자체도 사라지게 된다.

이 문제를 해결하기 위해선 QA 팀에 대한 정보는 놔두고, HYUNJIN에 대한 데이터만 NULL값을 주는 것이다.

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........nullnullnull
5nullnullnullnull1002QA5

하지만, 이 역시 null 값이 많이 쓰일 뿐더러 한눈에 봐도 괴상한 형태이다.

만약, 임직원 테이블과 부서 테이블을 따로 설계후 delete를 한다면 다음과 같다.

<EMPLOYEE>

empl_idempl_namebirth_datepositionsalarydept_id
1SUNGGON.........1001
2MINWOO.........1001
3SEHOON.........null

<DEPARTMENT>

dept_iddept_namedept_leader_id
1001DEV1
1002QAnull

임직원 테이블에서만 HYUNJIN의 데이터를 삭제하면 되고, 부서 테이블은 dept_leader_id만 null값으로 바꾸면 되는 것이다.

3. Update anomaly

empl_idempl_namebirth_datepositionsalarydept_iddept_namedept_leader_id
1SUNGGON.........1001DEV1
2MINWOO.........1001DEV1
3SEHOON.........???

- Spurious Tuples

잘못된 DB 스키마의 설계는 Spurious Tuples(가짜 튜플)이라는 문제점을 발생할 수도 있다.
예제를 통해서 Spurious Tuple에 대해 알아보자.

- NULL 값이 많아짐으로 인한 문제점들

- 바람직한 DB Schema 설계 방안


REF.

쉬운코드 - DB 테이블 설계 잘못하면 어떤 문제가 생길 수 있을까요?
데이터베이스 이상 현상(Anomaly) 개념과 예시
관계형 데이터 베이스의 함수적 종속성

profile
Pay it forward.

0개의 댓글