본문 바로가기

데이터베이스/오라클

테이블의 설계가 잘되었다라는걸 어떻게 증명할수 있을까?

나는 테이블을 설계할때 가장 주의 깊게, 심도있게 설계를 했다. 

그렇다보니 당연한게 되었다. 왜 테이블 설계가 잘 되었다라는 걸 생각하지 못했었다.

너무 당연하게 여겨졌던 행동들이었다.

 

그런데, 가만히 생각해보면 나만 알고 있었다. 남을 설득시켜야 했는데, 그러기 위해서는 체계화 시킬 필요가 있었다. 

그렇기에 체계화 해보려고 한다.

이론적인 부분을 설명하고 1정규화, 2정규화, 3정규화, BCNF정규화 내 경험에 비추어서 내가 세운 기준들을 말씀드리려 한다.

1정규화 : 컬럼의 원자이 유지되는가 이다

2정규화 : 특정 기본키에만 종속되는 부분적 종속이 없어야 한다.

3정규화 : 이행적 종속이 없어야 한다. A-> B, A->C일때, B->C를 결정하는걸 이행적 종속이라고 한다.

BCNF정규화 : 모든 결정자가 후보키 집합에 속해야 한다.

테이블 설계가 잘되었는지는 크게 4가지 포인트가 존재한다고 본다.

  • 컬럼이 원자성을 유지하는가?
  • 외부 테이블과 중복된 컬럼이 존재해서 관리 포인트가 2개 이상으로 늘어나지는 않는가?
  • 테이블에서 기본키 외에 Unique하게 Row를 추출할수 있는 Column이 존재하는가?
  • 컬럼에 중복되는 데이터가 많이 발생하는가? 그리고 그 컬럼을 결정짓는 요소가 기본키가 아닌가?

컬럼이 원자성을 유지하는가?

위를 잘 살펴보자.

어떤게 더 나은 형태인가를 생각해볼때 나는 무조건 1번이라 생각한다.

그 이유를 살펴보면

  • 예외적인 케이스가 발생하지 않는다.
  • 추가적인 비용이 발생하지 않는다.

하나 하나 살펴보자.

예외적인 케이스가 발생하지 않는다.

우리는 약속이라는 걸한다. 데이터베이스도 마찬가지다. 해당 Row의 Column값을 가져올때 1가지 값일 거라고 약속이라는 걸 하는것이다.

하지만 값이 2개 이상이라면?

  • 1개라고 예상할경우 해당값을 1개라고 생각해 프로그래밍했을때, 에러를 발생시킬수 있다.
  • 1개 이상이라면, 추가적인 가공을  해야 하므로 Application단에서 리소스 비용을 발생시킬 수 있다.
  • 이 말은 2개 이상이 들어갈수 있다는 말이므로, 해당 컬럼이 varchar(10)일 경우 강민준, 김아무개, 박아무개 의 데이터를 넣을때 에러를 발생시킬수 있다.

"위와 같은 이유로 나는 첫번째 경우가 맞다고 생각하며, 그래서 컬럼의 원자성을 유지해야 한다고 생각한다."

외부 테이블과 중복된 컬럼이 존재해서 관리 포인트가 2개 이상으로 늘어나지는 않는가?

2가지 테이블이 같은 값을 가진다고 생각해보자.(Cyber은 온라인 홈페이지로 가입한 회원, Member는 기존에 존재하던 회원이다)

만약, 온라인 홈페이지로 가입한 회원이 홈페이지에서 개명을 해서 이름을 바꾼다면 어떻게 할것인가 ?

Cyber만 바꿀것인가? Member와 동시에 바꿀것인가?

  • 둘다 바꾼다라고 한다면, Cyber에서 이름은 필요없다. Member에 존재하는 기본키만 외래키로 가지고 있으면 된다.
  • 관리적인 요소에서도 해를 끼친다. 어떤 개발자는 Cyber만 존재한다고 생각해서 Cyber만 바꾸는 프로그램을 만들수 있는것이고 그럴 경우 같은 사람이지만 다른 이름을 가지는 경우가 생길수 있다.

물론 예외적인 경우도 존재한다.

  •  결국 Join을 통해 값을 가져오므로, Join에 대한 비용이 크다면 반정규화를 해서 해당 문제를 해결할수도 있다.
  • 또한 "계약"의 경우 계약 원본을 그대로 저장해서 유지해야 하므로 다른값을 가질수 있다. 하지만 이런 예외적인 경우를 제외하고는 중복된 데이터를 가질 필요는 없다고 생각한다.

이블에서 기본키의 일부분 column(보통 후보키라고 부른다)이 unique하게 Row를 추출할수 있는가?

위와 같은 테이블이 존재한다고 가정하자. 위 테이블을 설계하면 다음과 같은 문제점이 생긴다.

Insert시

불필요하게 삽입시, customer_type과 custmer_type_nm을 알아야한다.

delete시

200번 회원번호 삭제시, 300번에 대한 customer_type과 custmer_type_nm정보를 모두 잃게 된다.

update시

100번 회원이 customer_type을 변경할시, 100번에 해당되는 모든행의 정보를 변경해야 한다.

관계를 따지자면 다음과 같은 관계가 된다고 생각한다.

customer_no가 unique하게 customer_type과 customer_type_nm을 추출할수 있다.

그렇다면 쪼개주어서 중복을 제거하는것이 좋다.

다음과 같이 2개의 테이블로 분리해준다.

컬럼에 중복되는 데이터가 많이 발생하는가? 그리고 그 컬럼을 결정짓는 요소가 기본키가 아닌가?

해당 테이블이 있다고 가정하자.

데이터가 쌓인다면 어떻게 될까?

customer가 Primary key라고 할때, 중복되는 데이터가 많이 쌓이는 느낌이 들지 않는가?

그 이유는 customer_type가 충분히 customer_type_nm을 결정지을수 있음에도  존재하기 때문이다.

그래서 해당 테이블을 다음과 같이 분리해야 한다.

눈에 보이게 중복된 데이터들이 없어지지 않았는가?

 

나는 항상 테이블을 설계할때, 위에 4가지 내세운 규칙을 지키려고 노력한다.

그리고 언제나 느끼지만, 결론은 데이터 중복과의 전쟁이다.

결론

결론은 "데이터 중복을 최소화 하자" 로 마무리 하겠다.

'데이터베이스 > 오라클' 카테고리의 다른 글

집계함수 RollUp  (0) 2022.08.03
Lock의 종류  (0) 2022.07.10
Partition Index  (0) 2022.03.09
Batch I/O  (0) 2022.03.09
바인드 변수  (0) 2022.03.09