데이터모델링
데이터 모델링이란 구축할 DB 구조를 약속된 표기법에 의해 표현하고 설계해 나가는 과정을 의미합니다.
데이터모델링의 단계
- 개념적 데이터 모델링
- 논리적 데이터 모델링
- 물리적 데이터 모델링
개념적 데이터 모델링
- 다이어그램을 통해 데이터베이스 구조를 시각화
- 이 단계는 추상화된 DB 구조를 그리는 것이므로 생략이 가능합니다.
- 사각형: 엔터티
- 원: 속성
- 마름모: 관계
논리적 데이터 모델링
- 구체적으로 데이터베이스를 설계합니다.
- 각 데이터의 타입, 관계, key 등을 지정합니다.
- erd cloud, draw.io, mysql 워크벤치 등의 툴을 써서 ERD를 그릴 수 있습니다.
- 엔터티: (엄밀히 말하면 다르지만,) DB의 한 테이블을 엔터티라고 생각하면 됩니다.
- ERD: 엔터티 간의 관계를 표현하는 다이어그램입니다.
- DB 설계에서 가장 중요한 단계라고 할 수 있습니다.
- 연관이 있는 테이블은 선으로 연결할 수 있는데, 엔터티 간의 관계에 따라서 다음 사진과 같이 표시할 수 있습니다.
간단히 정리해보자면
- 몇 대 몇인가
- 작대기: 1개 있어야함
- 삼발이: 여러개
- 필수 값인가
- 작대기: 필수
- 동그라미: 필수 아님
아래서 보게 될 테이블 간의 참조 관계 종류를 잘 고려하여 선으로 연결해주어야 합니다.
관련 용어 정리:
- reverse engineering: 기존 스키마(DDL 쿼리문)에서 ERD 추출 (워크벤치, 데이터그립 등의 툴에서 제공)
- forward engineering: ERD에서 스키마(DDL 쿼리문) 추출 (워크벤치, erd cloud 등의 툴에서 제공)
물리적 데이터 모델링
- 최종적으로 데이터베이스에 실제 테이블을 만드는 SQL 작업입니다.
- ERD에 표현되지 않는 부분들(예를 들면 인덱스)을 고려하여 테이블을 생성합니다.
테이블 간의 참조 관계
1:1 관계
- 한 테이블의 레코드(record, row)가 다른 테이블의 레코드 하나와만 연관 관계를 갖습니다.
- 1:1 관계를 보장하기 위해서는 fk를 unique 설정해줍니다.
- 1:1 관계 분리 필요성:
- 서비스의 특성을 기준으로 도메인의 명확한 분리를 통해 특정 서비스 변경 사항 발생 시 영향도를 최소화하고 유지 보수성 향상을 위해 1:1 테이블 관계로 분리하는 것이 필요할 때가 있습니다.
- ex) 회원과 회원의 주소 테이블: 회원이 한 개의 주소만 가질 수 있는 서비스가 있다면, 회원과 회원의 주소 테이블이 1:1 관계에 있습니다. 회원 테이블의 회원의 주소 정보까지 다 포함시켜도 되지만, 주소 체계가 복잡해서 country, city 등등 여러 컬럼으로 나눠야 하는 경우, 회원 테이블에 모두 포함시키면 회원 테이블의 컬럼이 너무 많아질 수 있으므로 주소 테이블을 분리하는 것이 좋습니다.
- 서비스의 특성을 기준으로 도메인의 명확한 분리를 통해 특정 서비스 변경 사항 발생 시 영향도를 최소화하고 유지 보수성 향상을 위해 1:1 테이블 관계로 분리하는 것이 필요할 때가 있습니다.
1:n 관계
A 테이블의 입장에서 생각했을 때, A 테이블의 한 레코드가 B 테이블의 여러 레코드와 관계가 있습니다.
ex) 게시판 서비스에서 author 테이블 입장에서 post 테이블과의 관계
n:1 관계
A 테이블 입장에서 생각했을 때, A 테이블의 여러 레코드가 B 테이블의 한 레코드와 관계가 있습니다.
ex) 게시판 서비스에서 post 테이블 입장에서 author 테이블과의 관계
n:m 관계
A 테이블의 한 레코드가 B 테이블의 여러 레코드와 관계가 있고, B 테이블의 한 레코드가 A 테이블의 여러 레코드와 관계가 있습니다.
ex) 백준 플랫폼에서 한 문제에는 여러 검수자가 있을 수 있고, 반대로 한 유저가 여러 문제를 검수할 수 있습니다.
-> n:m 관계는 나중에 살펴볼 제 1 정규화 규칙에 어긋납니다. 따라서 연결 테이블(junction table)을 만들어서 1:n 관계로 풀어주어야 합니다.
물론 n:m인 상태로 테이블을 만들어도 되기는 하지만, 한 컬럼에 여러 값들이 들어가기 때문에 조회, 수정, 삭제가 불편해집니다.
그 외 논리적/물리적 모델링을 할 때 고려해볼 것들
mandatory or optional
- 필수 값이라면 not null 조건을 걸어줍니다.
1:1 관계
- 1:1 관계를 보장해주고 싶다면 fk에 unique 조건을 걸어줍니다.
- ex) 하나의 글은 반드시 하나의 유저가 써야하는 게시판이 있다고 생각해봅시다. author, post, author_post(연결 테이블) 이렇게 3개의 테이블이 있을 때, author_post의 post_id(Post 테이블의 id를 참조하는 fk)를 unique로 걸어준다면, Post와 author_post가 1:1 관계가 되는 것이 보장됩니다.
회원 테이블에서 id(int or bigint) 대신에 email(unique)를 pk로 사용해도 될까?
회원 테이블에 있는 email column에 unique, not null 조건이 걸려있다면, 기존 id 대신 pk로 사용해도 될 것 같은데 이것은 좋은 설계일까요?
- 장점:
- id가 차지하는 만큼의 용량을 아낄 수 있습니다. (회원 테이블에서 id 컬럼을 날려도 되니까)
- 단점:
- email이 변경된다면 fk가 걸려있는 다른 테이블의 로우가 모두 cascade로 변경됩니다. fk는 기본적으로 인덱스가 걸리므로 여러 테이블에서 emaild(fk)에 대한 인덱스도 모두 변경될 것 같습니다.
- email을 fk로 참조하는 테이블이 많아질 수록 차지하는 용량이 커집니다. id는 int로 했을 때 4바이트, bigint로 했을 때 8바이트를 차지하지만, email은 최소 10자리 정도의 문자열로 구성되어 있을 것이고 길어질 경우 20자리 정도 된다고 생각하면 10바이트 ~ 20바이트를 차지하게 됩니다. 이 email을 pk로 써서 여러 테이블에서 fk로 참조하게 되면, id를 int, bigint 타입으로 설정하는 것보다 공간 낭비가 많이 발생할 것입니다.
-> 결론: id는 웬만하면 auto_increment 되는 int 또는 bigint를 쓰는 것이 좋을 것 같습니다.
uuid를 pk로 사용해도 될까?
- 장점:
- 분산 DB에서는 pk로 uuid를 쓰는 것이 유용합니다. (여러 DB에 흩어진 데이터를 다시 한 DB로 합칠 때 충돌이 발생할 가능성이 매우 적음)
- 단점:
- int(4바이트), bigint(8바이트) 타입의 pk보다 용량을 많이 차지합니다. (uuid는 36바이트)
-> 결론: 분산 DB 환경이 아니라면 id로 uuid를 쓰는 것은 추천하지 않습니다.
복합키의 사용
복합키란 2컬럼 이상에 PK 조건을 지정하는 것을 의미합니다.
ex) 복합키를 거는 테이블 생성 쿼리 예시
create table author_post(
author_id int,
post_id int,
created_time datetime default current_timestamp,
primary key(author_id, post_id), -- 복합키 설정. 둘에 같이 인덱스가 걸림
foreign key(post_id) references post(id),
foreign key(author_id) references author(id)
);
pk에는 자동으로 인덱스가 걸리는데, 복합키를 쓰면 두 컬럼에 동시에 인덱스가 걸립니다.
위 쿼리를 예시도 들었을 때, author_id
, post_id
에 동시에 인덱스가 걸리는 것이기 때문에, where author_id=1
이런 식으로 찾아올 때에는 인덱스가 걸리지 않습니다. where author_id=1 and post_id=3
이렇게 where 절을 써주어야 select 시에 인덱스를 활용할 수 있습니다.
- 장점:
- 불필요한 id 값을 추가할 필요가 없습니다.
- author_id, post_id 등 명확한 식별자를 통해 조회 시에 쿼리의 명확성이 향상됩니다. (Id 값은 보통 의미가 없는 숫자이기에 id로 조회하는 것보다 복합키로 조회하는 것이 쿼리의 의미를 이해하기 더 쉬울 수 있음)
- 단점:
- 프로그램의 복잡성이 증대됩니다.
-> 결론: 복합키는 쓰지 않고 별도의 pk(id)를 두는 것이 좋을 것 같습니다.
데이터모델링 외에도 오늘 정규화와 mariadb 덤프 실습을 진행했지만, sqld 시험이 얼마 남지 않은 관계로..,,,
그 내용들은 나중에 정리해보도록 하겠습니다. :)
Reference
- Beyond SW 7기 수업과 수업 자료
'개념 공부 > DBMS' 카테고리의 다른 글
[Redis] Redis 데이터의 영구 저장(RDB, AOF) (0) | 2024.12.10 |
---|---|
[DBMS] 트랜잭션(Transaction)이란 (0) | 2024.09.02 |
[Beyond SW / 7일차 복습 - 2] 정규형, DB Dump 실습 (1) | 2024.05.26 |
[DBMS] 트랜잭션 격리 레벨(isolation level) (0) | 2024.05.18 |