[SQL] DB 설계
1. 정규화 : 중복 없애기
- 중복 시 생기는 문제: 이상현상
- 왜 해야할까? 데이터의 무결성을 지키기 위해
2. DB 설계
- 디자인 보고 기능별로 저장해야하는 데이터 파악하기(UI가 나오기 전이라면, 요구사항 정의서를 보고 파악)
- 그룹핑해서 분류하기 (상위개념 찾기)
[예시]
- 아이디, 패스워드, 이름, 이메일 : 사용자
- 게시글 제목, 게시글 내용, 게시글 생성 시간 : 게시글
- 6가지 규칙에 의해 테이블(엔티티) 분리시키기
[ 규칙1. 한칸에는 한가지 정보만(제1정규형) ]
- 여러 정보가 들어갈 경우 데이터를 추출하고 또 가공해야해서 실수를 할 수 있다.
※ 한가지 정보: 서비스에서 데이터의 사용 방식에 따라 다르다 (성, 이름이 따로 필요한 경우 따로 저장)
[잘못된 예] 이메일 칸에 2가지 정보가 들어가있음
User | id(PK) | 이름 | 이메일 |
1 | 홍길동 | abc@naver.com, dfg@gmail.com | |
2 | 김철수 | qwe@kakao.com, zxc@gmail.com |
=> 테이블 분리
User | id(PK) | 이름 | |
1 | 홍길동 | ||
2 | 김철수 | ||
id(PK) | 이메일 | User id(FK) | |
1 | abc@naver.com | 1 | |
2 | dfg@gmail.com | 1 | |
3 | qwe@kakao.com | 2 | |
4 | zxc@gmail.com | 2 |
[ 규칙 2. FK를 넣어도 데이터가 중복이 될때 : 중간테이블을 하나 더 만들기 ]
[잘못된 예]
학생 | id(PK) | 이름 | 수강 과목 |
1 | 홍길동 | 수학, 과학 | |
2 | 김철수 | 국어, 수학 | |
3 | 김영희 | 국어, 과학 |
[1정규화]
학생 | id(PK) | 이름 | |
1 | 홍길동 | ||
2 | 김철수 | ||
3 | 김영희 | ||
수강 과목 | id(PK) | 과목명 | 학생 id (FK) |
1 | 수학 | 1,2 | |
2 | 과학 | 1,3 | |
3 | 국어 | 2,3 |
[중간테이블 만들기]
학생 | id(PK) | 이름 | |
1 | 홍길동 | ||
2 | 김철수 | ||
3 | 김영희 | ||
수강 과목 | id(PK) | 과목명 | |
1 | 수학 | ||
2 | 과학 | ||
3 | 국어 | ||
수강 과목 등록 (두 테이블의 관계를 나타내는 동사) |
id(PK) | 학생 id(FK) | 수강 과목 id(FK) |
1 | 1 | 1 | |
2 | 1 | 2 | |
3 | 2 | 1 | |
4 | 2 | 3 | |
5 | 3 | 2 | |
6 | 3 | 3 |
[ 규칙 3. 헷갈릴 땐 관계(1:1, 1:N, N:M)파악 ]
1) 사용자와 이메일
- 사용자가 이메일을 [소유한다]
- 이메일은 사용자에 의해 [소유되어진다]
- 하나의 사용자는 [여러개의] 이메일을 소유한다
- 하나의 이메일은 [한명의] 사용자에 의해 소유되어 진다.
- 사용자: 이메일 = 1:N => N쪽의 테이블에 FK가 들어가야 한다
2) 학생과 수강과목
- 학생이 수강과목을 [수강한다]
- 수강 과목이 학생에 의해 [수강된다]
- 한명의 학생은 [여러개의] 과목을 수강한다
- 하나의 수강과목은 [여러명의] 학생에 의해 수강된다.
- 학생:수강과목 = N:M
3) 1:1 관계는 어지간하면 분리하지 않는걸 추천
[ 규칙 4. 데이터 중복이 발생하는지 시뮬레이션을 돌려봐라 ]
[중복데이터 예시 - FK제외]
게시글 | id | 제목 | 내용 | 작성자 |
1 | 제목1 | 내용1 | 홍길동 | |
2 | 제목1 | 내용2 | 홍길동 | |
3 | 제목 | 내용3 | 홍길동 |
- 테이블 분리 : 작성자 이름이 변경 될 경우 모든 데이터를 바꿔야 하는 불편함이 있음
게시글 | id | 제목 | 내용 | 사용자 id(FK) |
1 | 제목 | 내용1 | 1 | |
2 | 제목 | 내용2 | 1 | |
3 | 제목 | 내용3 | 1 | |
사용자 | id | 이름 | ||
1 | 홍길동 |
[ 규칙 5. 가짜 중복과 진짜 중복을 구별]
- 실제 서비스에서 A 데이터 값을 수정하면 B 데이터의 값도 수정되어야 하는가?
- 홍길동 > 홍철수로 개명한 경우 작성자 다 바꿔야함 => 진짜 중복
- id 1의 제목이 제목1로 바뀌어도 id2의 제목을 제목1로 바꿀 필요는 없음. => 가짜 중복
[ 규칙 6. 숨어있는 중복을 찾자]
- 통계값들에서 중복 발생
[잘못된 예] *(참고) 성능에 문제가 생기는 경우 역정규화를 통해 중복을 허용하기도 함
게시글 | id | 제목 | 내용 | 좋아요 | 사용자 id (FK) |
1 | 제목1 | 내용1 | 같이 고쳐야함 (중복) |
1 | |
사용자 | id | 이름 | |||
1 | 홍길동 | ||||
2 | 김철수 | ||||
좋아요 | id | 사용자 id (FK) | 게시글 id (FK) | ||
1 | 1 | 1 | |||
[수정 후]
게시글 | id | 제목 | 내용 | 사용자 id (FK) |
1 | 제목1 | 내용1 | 1 | |
사용자 | id | 이름 | ||
1 | 홍길동 | |||
2 | 김철수 | |||
좋아요 | id | 사용자 id (FK) | 게시글 id (FK) | |
1 | 1 | 1 | ||
2 | 2 | 1 |
- 게시글 별 좋아요 수는 sum을 통해 따로 계산