물리 모델
고친 사람 github-actions[bot]
물리 모델은 데이터 설계를 실제로 쓸 데이터베이스 위에서 어떻게 저장할지까지 정합니다. 값마다 담을 형식을 고릅니다. 자주 찾는 값은 빨리 찾을 수 있게 합니다. 데이터 설계를 세 단계로 나눌 때 마지막 단계입니다. 제어나 시뮬레이션 분야에서는 물리 법칙으로 세운 계산 모델을 같은 이름으로 부릅니다.
쉽고 빠른 이해
무슨 일을 하나 — 표와 열까지 정해 둔 설계를 쓸 데이터베이스에 맞춰 마무리합니다. 고객번호를 8바이트 정수로 담습니다. 고객번호로 주문을 빨리 찾게 합니다.
왜 따로 두나 — 표와 열만으로는 데이터베이스가 표를 만들 수 없습니다. 값의 크기를 정해야 합니다. 어떤 조회가 자주 오는지에 맞춰 찾는 길도 깔아야 합니다. 이런 선택은 제품마다, 데이터 양마다 답이 달라서 설계 앞 단계와 떼어 둡니다.
어떻게 하나
- 쓸 데이터베이스 제품을 정합니다
- 열마다 담을 형식과 크기를 고릅니다
- 자주 오는 조회를 보고 빨리 찾는 장치를 붙입니다
- 결과를 데이터베이스에 표를 만드는 명령문으로 적습니다
대가 — 제품을 바꾸면 이 단계는 새로 해야 합니다. 서비스가 자라면서 조회 모양이 바뀌면 그때마다 고쳐야 합니다.
상세
집을 지을 때는 먼저 방이 몇 개 필요한지 정합니다. 그다음 벽 길이와 문 위치를 평면도에 그립니다. 마지막으로 시공 도면을 그립니다. 벽을 벽돌로 쌓을지 나무로 세울지, 배관을 얼마나 굵게 낼지가 이 도면에 들어갑니다.
데이터를 무엇으로 나누고 무엇으로 이을지 정하는 일이 데이터 모델링입니다. 집을 짓기 전에 도면을 그리듯, 데이터베이스를 만들기 전에 데이터의 모양을 먼저 정합니다. 이 일도 집처럼 흔히 세 단계로 나눕니다.
무엇을 다루는지만 적는 첫 단계가 개념 모델입니다. 집으로 치면 방이 몇 개 필요한지 정하는 일입니다. 그것을 표와 열로 옮긴 둘째 단계가 논리 모델입니다. 벽과 문을 그린 평면도에 해당합니다.
셋째 단계가 물리 모델입니다. 논리 모델을 특정 데이터베이스 제품 위에서 어떻게 저장할지까지 정합니다. 집으로 치면 시공 도면에 해당합니다.
아래에서는 쇼핑몰의 논리 모델 하나를 물리 모델로 옮기면서 물리 모델이 무엇을 정하는지 짚습니다. 끝에서는 논리 모델과 가르는 기준과, 같은 이름을 다른 뜻으로 쓰는 분야를 다룹니다.
세 단계가 정하는 내용
세 단계는 같은 쇼핑몰을 점점 더 자세히 적습니다. 단계마다 무엇을 정하는지 모았습니다.
| 단계 | 정하는 것 | 쇼핑몰에서 |
|---|---|---|
| 개념 모델 | 다룰 대상과 그 사이의 관계 | 고객이 주문을 한다 · 주문에 상품이 담긴다 |
| 논리 모델 | 표 · 열 · 표 사이의 관계 | 주문 표에 고객번호 열을 두어 고객 표를 가리킨다 |
| 물리 모델 | 쓸 제품 · 값의 형식 · 빨리 찾는 장치 | 고객번호를 8바이트 정수로 담는다 · 고객번호로 주문을 빨리 찾게 한다 |
위 두 단계는 제품을 모릅니다. 물리 모델에 와서야 제품이 정해집니다.
출발점이 되는 논리 모델
물리 모델은 빈손으로 시작하지 않습니다. 논리 모델이 이미 표와 열을 정해 두었습니다. 쇼핑몰이라면 표가 넷입니다.
| 표 | 열 |
|---|---|
| 고객 | 고객번호 · 이름 · 이메일 |
| 상품 | 상품번호 · 상품명 · 가격 |
| 주문 | 주문번호 · 고객번호 · 주문일 |
| 주문항목 | 주문번호 · 상품번호 · 수량 |
각 표의 번호 열은 기본 키입니다. 표 안에서 행 하나를 가려내는 열입니다. 고객번호가 같은 고객이 둘일 수 없으니 고객번호 하나로 고객 한 명이 정해집니다.
주문 표의 고객번호처럼 다른 표의 기본 키를 적어 둔 열은 외래 키입니다. 이 열 덕분에 주문 하나를 보고 누가 주문했는지 찾아갈 수 있습니다.
이 표에는 아직 빠진 것이 있습니다. 고객번호가 얼마나 큰 수까지 커지는지, 가격을 어떤 수로 담는지가 없습니다. 고객번호로 주문을 찾을 때 표 전체를 훑을지도 정하지 않았습니다. 물리 모델이 채우는 것이 이 빈칸입니다.
쓸 제품을 먼저 정하기
물리 모델의 첫 결정은 어느 데이터베이스 제품을 쓸지입니다. 제품마다 고를 수 있는 형식과 장치가 다릅니다. 같은 이름의 형식이라도 담는 값이 다르기도 합니다. Oracle 의 DATE 는 시각까지 담지만 PostgreSQL 의 DATE 는 날짜만 담습니다.
그래서 같은 논리 모델 하나에서 제품마다 다른 물리 모델이 나옵니다. 제품을 바꾸면 물리 모델만 새로 짭니다. 그 위 두 단계는 손대지 않고 남깁니다.
flowchart TD
A[개념 모델] --> B[논리 모델]
B --> C["물리 모델 · PostgreSQL"]
B --> D["물리 모델 · MySQL"]
C --> E["PostgreSQL 의 테이블 생성문"]
D --> F["MySQL 의 테이블 생성문"]
그림에서 갈라지는 곳은 논리 모델 아래 한 군데뿐입니다. 제품에 따라 달라지는 결정이 전부 물리 모델 안에 모여 있기 때문입니다.
값마다 담을 형식 고르기
열마다 어떤 값을 어떤 크기로 담을지 정합니다. 이 글이 말하는 형식이 곧 데이터 타입입니다. 정수·글자·날짜 같은 값의 종류에 그 값이 차지하는 크기까지 묶은 것이라, 4바이트 정수와 8바이트 정수는 서로 다른 데이터 타입입니다. 데이터베이스는 데이터 타입을 보고 값을 담을 공간을 잡습니다.
쇼핑몰의 열 몇 개에 형식을 골라 보면 이렇습니다.
| 열 | 고른 형식 | 고른 까닭 |
|---|---|---|
| 고객번호 · 주문번호 | 8바이트 정수 | 4바이트 정수는 약 21억에서 막힌다 |
| 이메일 | 길이가 바뀌는 문자열 | 주소마다 길이가 다르다 |
| 가격 | 고정소수점 수 | 돈 계산에 오차가 생기면 안 된다 |
| 주문일 | 날짜 형식 | 날짜끼리 비교하고 정렬해야 한다 |
첫 줄은 크기의 문제입니다. 4바이트 정수는 약 21억까지만 담습니다. 주문이 쌓여 그 수를 넘으면 새 주문에 번호를 매길 수 없습니다. 8바이트 정수는 약 922경까지 담습니다. 대신 행마다 4바이트를 더 씁니다.
셋째 줄은 정확도의 문제입니다. 소수를 담는 흔한 방법인 부동소수점은 값을 2진수로 어림해 담습니다. 그래서 0.1 같은 값이 아주 조금 어긋난 채 저장됩니다.
가격에 고른 고정소수점은 소수점 아래 자릿수를 미리 정해 둡니다. 값은 10진수 그대로 담습니다. 그래서 이런 어긋남이 없습니다.
넷째 줄은 비교의 문제입니다. 날짜를 글자로 담으면 「3월」과 「10월」 같은 값을 글자 순서로 정렬하게 됩니다. 그러면 「10월」이 「3월」보다 앞에 섭니다. 날짜 형식으로 담으면 데이터베이스가 날짜로 알고 앞뒤를 가립니다.
빨리 찾는 길 깔기
쇼핑몰은 「이 고객의 주문 목록」을 자주 묻습니다. 아무 장치가 없으면 데이터베이스는 주문 표의 행을 처음부터 끝까지 다 읽어 고객번호를 맞춰 봅니다. 주문이 천만 건이면 천만 행을 읽습니다.
이를 막는 장치가 인덱스입니다. 어느 고객번호가 어느 행에 있는지 따로 정렬해 적어 둔 목록입니다. 책 뒤의 찾아보기처럼 표 전체를 훑지 않고도 원하는 행으로 바로 갑니다.
인덱스는 공짜가 아닙니다. 주문이 하나 들어올 때마다 표와 함께 인덱스도 고쳐야 해서 쓰기가 느려집니다. 인덱스를 담을 디스크 공간도 따로 듭니다. 그래서 모든 열에 걸지 않고 자주 오는 조회에 쓰이는 열만 고릅니다.
여기서 물리 모델의 성격이 드러납니다. 논리 모델은 어떤 데이터가 있는지만 봅니다. 물리 모델은 그 데이터를 어떤 조회가 얼마나 자주 읽는지까지 봅니다.
큰 표를 나눠 담기
주문 표는 시간이 갈수록 계속 커집니다. 몇 년이 지나면 오래된 주문이 표의 대부분을 차지합니다. 그런데 조회는 대개 최근 주문에 몰립니다.
이럴 때 표 하나를 여러 조각으로 나눠 담는 파티셔닝을 씁니다. 주문 표를 달마다 한 조각씩 나누면, 이번 달 주문을 찾을 때 이번 달 조각만 읽습니다. 3년 지난 주문을 지울 때도 그 달 조각을 통째로 떼어 내면 됩니다.
나눌지, 무엇을 기준으로 나눌지는 데이터가 얼마나 쌓이는지에 달렸습니다. 논리 모델 단계에서는 이 양을 따지지 않습니다. 그래서 이 결정도 물리 모델에서 내립니다.
일부러 되풀이해 적기
논리 모델은 같은 내용을 한 곳에만 적도록 표를 나눕니다. 이렇게 되풀이를 걷어 내며 표를 나누는 일이 정규화입니다. 고객 이름은 고객 표에만 있습니다. 주문 표는 고객번호만 들고 있습니다.
그러면 주문 목록 화면에 고객 이름을 띄울 때마다 두 표를 이어 붙여 읽어야 합니다. 여러 표를 공통 열로 이어 읽는 이 연산이 조인입니다. 이 화면이 아주 자주 불리면 조인 비용이 쌓입니다.
물리 모델은 이때 주문 표에 고객 이름을 한 번 더 적어 두는 쪽을 고를 수 있습니다. 정규화로 걷어 낸 되풀이를 이렇게 속도 때문에 다시 들이는 일이 반정규화입니다. 대가는 고객이 이름을 바꿀 때 두 표를 함께 고쳐야 한다는 것입니다.
결과물이 되는 테이블 생성문
물리 모델의 결정은 결국 데이터베이스에 표를 만드는 명령문으로 적힙니다. 표와 인덱스처럼 데이터베이스 안의 구조를 정의하는 명령이 DDL(Data Definition Language, 데이터 정의 언어)입니다. 표(테이블)를 만드는 테이블 생성문이 그 대표입니다.
아래는 주문 표의 물리 모델을 SQL(Structured Query Language, 구조화 질의 언어)로 적은 것입니다. 오른쪽 주석이 앞 소절의 결정을 가리킵니다.
CREATE TABLE orders (
id BIGINT PRIMARY KEY, -- 주문번호
cust_id BIGINT NOT NULL, -- 고객번호
ordered DATE NOT NULL, -- 주문일
cust_nm VARCHAR(50) -- 반정규화
);
CREATE INDEX idx_orders_cust
ON orders (cust_id); -- 고객별 조회
BIGINT 는 8바이트 정수입니다. VARCHAR(50) 은 길이 상한을 50으로 둔, 길이가 바뀌는 문자열입니다. 마지막 두 줄이 고객번호로 주문을 빨리 찾게 하는 인덱스입니다.
NOT NULL 은 이 열을 비워 둘 수 없다는 규칙입니다. 저장할 값이 지켜야 할 이런 규칙이 제약조건입니다. 주문일 없는 주문은 어느 제품에 담아도 안 되므로, 이 규칙은 제품을 모르는 논리 모델 몫입니다. 테이블 생성문에는 이처럼 두 단계의 결정이 함께 적힙니다.
쌓이는 데이터를 따라 고치는 모델
물리 모델은 서비스를 열기 전에 한 번 짜고 끝나지 않습니다. 처음에는 데이터가 얼마나 쌓일지, 어떤 조회가 몰릴지 어림으로 정합니다. 서비스를 굴려 보면 그 어림이 틀린 곳이 나옵니다.
오래 걸리는 조회가 보이면 데이터베이스가 그 조회를 어떤 순서로 처리했는지 들여다봅니다. 이 처리 순서가 실행 계획입니다. 실행 계획에서 표 전체를 훑고 있으면 인덱스를 더하거나 표를 나누는 쪽으로 물리 모델을 고칩니다.
운영 중인 표를 고칠 때는 바꾼 내용을 순서 있는 변경 스크립트로 남기는 스키마 마이그레이션을 씁니다. 이렇게 물리 모델이 여러 번 바뀌는 동안에도 논리 모델은 대개 그대로 남습니다.
문서 없이 코드로 남는 물리 모델
작은 서비스에서는 물리 모델을 따로 그림이나 문서로 남기지 않는 일이 흔합니다. 테이블 생성문과 마이그레이션 스크립트가 곧 물리 모델입니다.
표가 많아지거나 여러 팀이 같은 데이터베이스를 쓰면 사정이 달라집니다. 왜 이 열에 인덱스를 걸었는지, 왜 이 표를 달마다 나눴는지를 코드만 보고는 알기 어렵습니다. 그럴 때 물리 모델을 문서로 남겨 결정의 까닭을 함께 적어 둡니다.
논리 모델과 가르는 기준
어떤 결정이 논리 모델 몫인지 물리 모델 몫인지 헷갈릴 때가 있습니다. 가르는 물음은 하나입니다. 「제품을 바꾸면 이 결정도 바뀌나」입니다.
| 결정 | 제품을 바꾸면 | 속하는 단계 |
|---|---|---|
| 두 고객이 같은 이메일을 쓸 수 없다 | 안 바뀐다 | 논리 모델 |
| 주문 표에 고객번호 열을 둔다 | 안 바뀐다 | 논리 모델 |
| 주문일은 비워 둘 수 없다 | 안 바뀐다 | 논리 모델 |
| 고객번호를 8바이트 정수로 담는다 | 바뀔 수 있다 | 물리 모델 |
| 주문 표를 달마다 나눠 담는다 | 바뀔 수 있다 | 물리 모델 |
위 세 줄은 업무 규칙입니다. 어느 제품에 담든 쇼핑몰은 같은 규칙을 지킵니다. 아래 두 줄은 저장 방법입니다. 제품이 지원하는 형식과 장치에 따라 답이 달라집니다.
같은 이름을 쓰는 다른 분야
제어나 시뮬레이션 분야에도 물리 모델이라는 말이 있습니다. 거기서는 열이 퍼지는 방식이나 물체가 움직이는 방식을 물리 법칙의 식으로 세운 계산 모델을 가리킵니다.
이 뜻의 물리 모델은 측정값만으로 맞춘 데이터 기반 모델과 맞세워 부릅니다. 데이터 설계의 물리 모델과는 이름만 같습니다.
관련 항목
물리 모델이 속하는 설계 단계
데이터 모델링 · 개념 모델 · 논리 모델 · 데이터베이스 설계 · 스키마 · ANSI-SPARC 아키텍처 · 데이터 독립성
물리 모델이 넘겨받는 논리 모델의 구성 요소
테이블 · 열 · 행 · 기본 키 · 외래 키 · 제약조건 · 정규화 · 조인
물리 모델에서 고르는 저장 방법
데이터 타입 · 인덱스 · 클러스터드 인덱스 · 복합 인덱스 · 파티셔닝 · 샤딩 · 반정규화 · 구체화 뷰 · 압축
물리 모델을 이루는 데이터베이스 내부 구조
스토리지 엔진 · B-tree · 페이지 · 버퍼 풀 · 테이블스페이스 · 파일 시스템
물리 모델을 검증하고 고치는 수단
실행 계획 · 쿼리 옵티마이저 · 풀 테이블 스캔 · 스키마 마이그레이션 · 용량 계획
물리 모델을 적는 언어와 도구
SQL · DDL · ORM · ER 다이어그램
물리 모델을 받아 담는 데이터베이스 제품
관계형 데이터베이스 · PostgreSQL · MySQL · Oracle · 문서 데이터베이스
물리 모델과 이름이 겹치는 다른 분야의 모델
데이터 기반 모델 · 물리 기반 모델 · 시뮬레이션 · 디지털 트윈
다른 이름: physical model · physical data model · 물리 데이터 모델 · 물리적 데이터 모델 · 물리적 모델