본문 바로가기

물리 DB 설계·인덱스·파티션

문구점의 고객·상품·주문·주문항목은 앞 절에서 서로 다른 사실로 나눴다. 주문 O101의 배송지 A와 확정금액 23,000원도 현재주소·현재가격이 바뀌어도 보존한다. 그런데 주문이 백만 건으로 늘어도 화면이 제때 열리는지는 아직 정하지 않았다. 한 행의 크기, 원하는 행으로 가는 경로, 오래된 데이터의 보관과 변경 …

0. 표가 올바른 것과 빨리 안전하게 읽히는 것은 다른 문제다

문구점의 고객·상품·주문·주문항목은 앞 절에서 서로 다른 사실로 나눴다. 주문 O101의 배송지 A와 확정금액 23,000원도 현재주소·현재가격이 바뀌어도 보존한다. 그런데 주문이 백만 건으로 늘어도 화면이 제때 열리는지는 아직 정하지 않았다. 한 행의 크기, 원하는 행으로 가는 경로, 오래된 데이터의 보관과 변경 중 실패가 남아 있기 때문이다.

물리 설계는 같은 업무 의미를 어느 저장 구조와 접근 방법으로 구현할지 결정한다. 인덱스 하나가 읽을 데이터의 양을 줄이는 대신 새 주문의 쓰기 작업량과 필요한 저장공간을 늘릴 수 있다. 이 절은 요구와 논리모델을 바꾸지 않은 채 선택의 이득·비용·실패조건을 연결한다.

앞 두 절의 데이터 모델링으로 문구점의 사실·관계·규칙을 고객·상품·주문·주문항목의 표와 키·제약에 옮겼다(개념·논리 모델과 정규화: 뜻을 잃지 않고 표를 나눈다). 질의는 필요한 결과를 지정하고 인덱스는 그 결과로 가는 보조 경로였으므로, 어떤 값을 자주 찾느냐가 접근 방법의 선택에 중요했다(데이터베이스 관리시스템(DBMS)·질의·인덱스). 이제 그 뜻을 유지하면서 실제 저장과 접근 방법을 정한다.

1. 물리 설계는 요구를 실제 저장·접근·운영 선택으로 바꾼다

물리 데이터베이스 설계는 논리모델의 의미와 제약을 유지하면서 선택한 DBMS의 자료형·행과 저장 구조·인덱스·분할·용량 및 운영 설정으로 구현하는 과정이다. 목표는 읽기 속도 하나가 아니라 정확성, 응답시간, 쓰기 처리, 저장비용과 복구 가능성을 함께 충족하는 것이다.

입력은 표·키·관계·업무규칙, 주요 질의와 변경의 빈도·건수·동시성, 증가량·보존·성능·복구 요구, 사용할 제품과 버전이다. 산출물은 물리 스키마, 자료형·제약과 인덱스 목록, 저장·분할·용량 계산, 선택·기각 이유와 검증 기준이다. 물리 스키마는 앞서 배운 스키마 계약을 제품에서 구현할 이름·자료형·제약·저장 선택으로 구체화한 것이다.

선택은 요구 → 후보 → 예상 비용 → 같은 조건의 측정 → 채택 또는 수정으로 연결한다. 논리적 기본키를 정했다고 실제 파일의 행 순서까지 정해지는 것은 아니고, 인덱스를 만들었다고 최적화기가 항상 그 경로를 택하는 것도 아니다.

전체 지도: 바꾸지 않을 뜻에서 검증할 결과까지

업무의 뜻을 지킨 후보만 채택한다

상자 안의 대상과 화살표의 조건을 함께 읽으세요. 좁은 화면에서는 같은 관계를 세로로 재배치한 도식을 보여 줍니다.

업무의 뜻을 지킨 후보만 채택한다상단은 바꾸지 않을 업무 의미를 실제 표현·접근 후보로 옮기는 흐름이다. 용량과 동일 조건 검증 뒤 수용기준을 모두 충족할 때 채택한다. 미달이면 후보와 가정을 다시 살피며 원래 규칙을 지우지 않는다.requirements → types: 표현types → layout: 접근layout → capacity: 공간capacity → check: 검증check → accepted: 충족check → revise: 미달revise → layout: 다시 선택표현접근공간검증충족미달다시 선택업무 의미·키·보존 규칙: 읽기·쓰기 요구업무 의미·키·보존 규칙읽기·쓰기 요구자료형·제약·비교 기준자료형·제약·비교 기준행 배치·인덱스·분할행 배치·인덱스·분할본체·인덱스·복구·여유본체·인덱스·복구·여유기준을 모두 충족?기준을 모두충족?채택: 정확성·읽기·쓰기·복원채택정확성·읽기·쓰기·복원후보·가정 재검토후보·가정 재검토
업무의 뜻을 지킨 후보만 채택한다상단은 바꾸지 않을 업무 의미를 실제 표현·접근 후보로 옮기는 흐름이다. 용량과 동일 조건 검증 뒤 수용기준을 모두 충족할 때 채택한다. 미달이면 후보와 가정을 다시 살피며 원래 규칙을 지우지 않는다.requirements → types: 표현types → layout: 접근layout → capacity: 공간capacity → check: 검증check → accepted: 충족check → revise: 미달revise → layout: 다시 선택표현접근공간검증충족미달다시 선택업무 의미·키·보존 규칙: 읽기·쓰기 요구업무 의미·키·보존 규칙읽기·쓰기 요구자료형·제약·비교 기준자료형·제약·비교 기준행 배치·인덱스·분할행 배치·인덱스·분할본체·인덱스·복구·여유본체·인덱스·복구·여유기준을 모두 충족?기준을모두충족?채택: 정확성·읽기·쓰기·복원채택정확성·읽기·쓰기·복원후보·가정 재검토후보·가정재검토

상단은 바꾸지 않을 업무 의미를 실제 표현·접근 후보로 옮기는 흐름이다. 용량과 동일 조건 검증 뒤 수용기준을 모두 충족할 때 채택한다. 미달이면 후보와 가정을 다시 살피며 원래 규칙을 지우지 않는다.

화살표는 앞 판단이 다음 판단의 입력이 된다는 뜻이다. 뒤에서 응답시간이 줄었더라도 앞에서 정한 주문번호 유일성이나 과거 배송지 보존이 깨졌다면 채택할 수 없다. 검증에 실패하면 해당 저장·접근 후보와 가정을 다시 살피며, 업무 규칙을 조용히 없애서 성능을 맞추지 않는다. 각 상자의 구체적인 이론과 판단 방법은 바로 뒤에서 차례대로 읽는다.

같은 문구점 사례에 사용량과 측정 범위를 붙인다

앞 절의 설명용 요구는 고객별 최근 90일 주문을 최신순 20건씩 조회, 동시 조회 100건을 유지한 30분 동안 요청부터 결과 수신까지 p95 300ms 이내였다. p95는 관측 응답시간의 95번째 백분위다. 유한 표본의 동률·보간·올림 방식에 따라 그 값 이하인 비율이 정확히 95%는 아닐 수 있으므로 계산 방식과 표본 수를 함께 정한다. 평균이 빠르다는 말로 이 기준을 대신하지 않는다.

사용 흐름조건·결과물리 설계에서 물을 것
고객 주문 목록고객번호가 같은 최근 90일, 시각 내림차순, 최대 20건고객과 시각으로 좁힌 뒤 정렬을 줄일 수 있는가
주문 상세주문번호 1개와 그 항목들주문 키와 항목 키를 따라 적은 행을 읽는가
월별 집계정한 월의 주문·항목을 모아 합계넓은 범위를 순차적으로 읽는 편이 나은가
작성중 주문 변경항목 추가·수량 변경원본뿐 아니라 인덱스·제약을 유지할 비용은 얼마인가
확정·취소기존 R04·R06의 상태 전환과 원주문 보존조회용 중복값도 같은 업무 규칙을 지키는가
기간별 보관합의한 보존기간의 데이터필요한 기간만 읽고 안전하게 보관·폐기할 수 있는가

계산용 증가량은 하루 주문 1,000건, 주문당 평균 3개 항목이다. 365일 동안 주문 365,000행과 주문항목 1,095,000행이 늘어난다. 이는 예측 가정이며 법정 보존기간이나 실측 부하가 아니다. 실제 보존기간과 기간 만료 때의 예외는 근거 있는 요구로 별도로 확정한다.

표 이름보다 먼저 바꾸면 안 되는 사실을 고정한다

논리적 사실유지할 규칙물리 후보에서 확인할 부분
고객고객번호로 식별, 현재주소는 현재 사실식별자 표현·유일 제약, 주소 길이
상품상품번호로 식별, 현재가격은 상품의 현재 사실가격의 정확한 수 표현과 범위
주문주문번호로 식별, 고객 참조, 당시 배송지·취소사유 보존키·외래키, 주문시각·배송지·취소사유 저장, 취소 시 사유 필수 검사
주문항목주문번호·항목번호로 줄 식별, 상품·수량·확정단가복합키, 참조, 수량 검사와 단가 표현

같은 상품을 한 주문의 여러 항목번호로 나눌 수 있으므로 물리 기본키 후보도 주문번호·항목번호의 유일성을 보존한다. 빠르게 조회하려고 주문번호·상품번호를 무조건 유일하게 만들면 R04를 바꿔 버린다. 확정단가를 현재가격 참조로 치환하거나 배송지를 현재주소로 덮어쓰는 것도 물리 최적화가 아니라 사실의 손실이다.

자료형은 허용할 값과 연산을 정하고 무결성은 저장된 값이 정한 규칙을 지키는 성질이었다(값·변수·자료형·연산, 정규화·중복·무결성). 부동소수점은 일부 수를 근사하며, 문자 인코딩에 따라 같은 문자 수도 저장 바이트 수가 달라진다(정수·부호·고정소수점·부동소수점, 문자·인코딩·직렬화·엔디언). 문구점의 금액·주소를 어떤 제품 자료형과 제약으로 옮길지 판단할 때 이 경계가 함께 필요하다.

2. 열의 뜻을 자료형·길이·비교 규칙으로 구현한다

물리 도메인 매핑은 업무 값의 뜻·단위·허용 범위·빈값·비교 규칙을 선택한 DBMS의 자료형과 제약에 대응시키는 작업이다. 같은 금액이라도 정수 원 단위인지 소수 단위를 쓰는 통화인지 먼저 정한다. 같은 문자열 자료형이라도 식별자와 사람 이름은 길이·대소문자·공백의 의미가 다를 수 있다.

업무 도메인은 허용할 값과 의미이고 제품 자료형은 그것을 구현하는 수단이다. 충분한 저장 범위만 고르면 끝나는 것이 아니다. 원본에서 들어온 값의 변환·반올림·잘림이 허용되는지, 프로그램과 DB가 같은 값을 비교하는지도 검사해야 한다.

금액은 큰 수보다 정확한 수라는 조건이 먼저다

앞의 문구점은 원 단위의 정확한 금액을 사용했다. 충분한 범위의 정수 또는 정확한 십진수 자료형이 후보이고, 근삿값을 저장하는 부동소수점을 금액의 정확한 동등성 판단에 그대로 쓰지 않는다. 수량과 단가가 각각 범위 안이어도 둘의 곱이나 주문 합계가 더 큰 범위를 요구한다.

십진수 자료형에서 정밀도는 저장할 전체 유효 숫자 수이고 스케일은 소수점 아래 자릿수다. 예를 들어 일반적인 양의 스케일을 쓰는 NUMERIC(7,2)는 전체 7자리 중 2자리를 소수 부분에 배정한다. PostgreSQL 18에서는 99,999.99까지 표현하지만 100,000.00은 정수 부분이 넘는다. 1.235를 넣으면 소수 2자리로 반올림되어 1.24가 된다. 그러므로 정확한 십진수형이면 입력값이 항상 원형 그대로 남는다도 틀리다.

이 자료형 예시는 단위를 바꾼 문구점의 새 요구가 아니다. 문구점의 원 단위 단가는 소수 부분을 허용할지부터 검증하고, 반올림이 허용되지 않는 입력은 저장 전에 거부하는 규칙을 둔다. 제품별 정수 범위·십진 반올림과 실제 저장 길이는 버전 문서로 확인한다.

앞의 자릿수 설명은 스케일이 0 이상이고 정밀도 이하인 보통의 선언부터 읽은 것이다. PostgreSQL 18은 음의 스케일도 허용한다. 예를 들어 NUMERIC(2,-3)은 소수점 왼쪽의 천 단위로 반올림하고, 스케일이 정밀도보다 큰 NUMERIC(3,5)는 -0.00999부터 0.00999까지의 작은 소수를 표현한다. 따라서 모든 제품·선언에서 정수 부분 자릿수=정밀도−스케일만 기계적으로 적용하지 않고, 선택한 제품의 허용 선언과 변환 규칙을 확인한다.

이름의 글자 수와 저장 바이트, 같은 이름의 기준은 다르다

가변길이 문자형 VARCHAR는 실제 문자열 길이에 따라 저장하고, 고정길이 문자형 CHAR는 정해진 길이에 맞추어 다루는 문자형이다. PostgreSQL 18의 varchar(20)에서 20은 바이트가 아니라 문자 수다. 같은 20문자라도 인코딩과 문자 조합에 따라 저장 바이트가 달라진다. 이 제품의 CHAR는 공백을 채우며 비교에서 뒤 공백을 무시하는 특성이 있으므로 제품의 형식 이름만 보고 다른 DBMS까지 일반화하지 않는다.

문자 정렬·비교 규칙인 콜레이션(collation)은 문자열의 순서와 비교를 어떤 언어·문자 규칙으로 처리할지 정한다. 대문자·소문자나 악센트 차이를 구별할지는 입력을 정리하는 규칙과 DB의 비교 규칙을 함께 맞춰야 한다. 사람이 같은 이름을 쓴다는 사실만으로 두 고객을 합치지 않고 고객번호로 식별하는 R01도 유지한다.

문구점의 상품코드 P1과 p1을 같게 볼 것인지, 뒤 공백을 허용할 것인지 먼저 정한 뒤 유일 제약과 검색을 시험한다. 주소의 허용 길이를 늘릴 때는 프로그램 입력 길이, 연계 파일과 인덱스 공간도 함께 확인한다.

날짜와 사건이 일어난 순간을 구분한다

2026-09-01이라는 업무 날짜와 그날 09시 30분에 주문했다는 사건 시각은 다른 값이다. 타임스탬프(timestamp)는 날짜와 시각을 함께 나타내는 값이며, 시간대 처리가 있는지에 따라 해석이 달라진다. UTC(협정 세계시)는 서로 다른 지역의 시각을 맞추는 공통 기준 시간이다. 지역 시각과 UTC의 차이를 나타내는 값을 시간대 오프셋이라고 한다.

PostgreSQL 18의 timestamp with time zone은 입력의 시간대 정보를 사용해 같은 순간을 UTC 기준으로 저장하고, 조회할 때 설정된 시간대로 보여 준다. 하지만 원래 입력에 사용한 지역 시간대 이름까지 함께 보존하지는 않는다. 주문이 일어난 순간뿐 아니라 당시 어느 지역의 시계로 해석했는가가 업무 사실이라면 그 정보도 별도 열에 남긴다.

이름에 time zone이 없는 타임스탬프를 쓰면서 서로 다른 지역 입력을 그냥 섞으면 같은 09:30이 서로 다른 순간을 가리킬 수 있다. 고객별 최근 주문의 범위와 월별 집계의 날짜 경계도 어떤 시간 기준인지 정해야 일관되게 나온다.

작은 열 선택이 큰 데이터 오류로 이어지는 경우

선택 오류반례·증상통제
금액에 근삿값 자료형 사용같은 금액 비교·합산이 기대와 달라짐정확한 단위·형과 계산 범위 선택
십진수형이면 변환이 없다고 믿음1.235가 스케일 2에서 1.24로 바뀜반올림 허용 여부와 입력 검증
문자 수를 바이트 수로 계산한글·다국어에서 용량·연계 제한 초과인코딩과 실제 길이 분포 측정
코드의 비교 규칙 미합의P1/p1 또는 뒤 공백의 중복 판정 불일치입력 정리·콜레이션·유일성 시험
시각에 시간 해석 기준 없음최근 90일·월 경계의 포함 결과가 달라짐사건 순간·지역 기준·집계 경계 명시
값 범위와 빈값을 한 검사로 처리수량의 빈값이 양수 검사만으로 걸러지지 않음앞 절의 NOT NULL과 값 범위 제약을 함께 적용

R06을 PostgreSQL 18에 옮기는 작은 후보는 주문상태를 NOT NULL로 두고 작성중·확정·취소만 허용하며, 취소사유는 가변길이 문자형으로 저장하는 것이다. 상태별 필수 조건은 다음처럼 현재 행에서 검사할 수 있다.

코드를 먼저 말로 읽으면 IN은 괄호의 허용 목록 중 하나와 같은지, <>는 서로 다른지를 묻는다. IS NOT NULL은 빈값 표지가 아닌지 검사하고, AND는 양쪽 조건을 모두, OR는 적어도 한쪽 조건을 만족하라는 뜻이다. 작은따옴표는 상태·사유의 문자값을 감싸고, 괄호는 함께 판단할 조건을 묶는다. 따라서 둘째 CHECK는 취소가 아니거나, 취소라면 사유가 NULL도 빈 문자열도 아니어야 한다로 읽는다.

CHECK (주문상태 IN ('작성중', '확정', '취소'))
CHECK (주문상태 <> '취소'
       OR (취소사유 IS NOT NULL AND 취소사유 <> ''))

이 조각은 완성 DDL이 아니라 앞 논리규칙의 조건부 필수 검사를 보여 준다. 취소 상태에서 사유가 NULL이면 IS NOT NULL이 거짓이 되어 거절되고, 빈 문자열도 거절된다. 사유가 공백만인 등 의미 없는 입력의 정리·거절 규칙과 허용 길이는 주문 담당이 별도로 정한다. 상태의 NOT NULL을 빼면 CHECK만으로 미정 상태까지 막았다고 할 수 없다. 현재 행의 검사만으로 취소→확정 직접전환이나 원주문 값 덮어쓰기를 막는 것도 아니므로, 허용된 변경 경로에서 상태·사유의 동시 기록과 원래 배송지·확정단가·수량 보존을 함께 집행한다.

기본키·외래키·필수·값 범위 제약은 논리규칙을 제품에 옮긴 것이다. 모든 업무 규칙이 한 행의 값 검사로 표현되는 것은 아니다. 주문 전체 합계나 확정 때의 항목 존재처럼 여러 행·상태에 걸친 규칙은 앞 절에서 정한 트랜잭션과 검증 책임을 잃지 않는다.

파일은 이름으로 관리하는 데이터 묶음이고 저장장치와의 처리는 블록 단위로 이루어지며, 바이트는 그 크기를 세는 단위였다(파일·블록·영속 저장, 비트·바이트·진법과 논리값). 메모리 계층에서는 이미 빠른 곳에 있는 데이터를 읽는 것과 저장장치에서 새로 가져오는 것의 비용이 달랐다(주소·참조·메모리 계층). 이제 한 행의 길이뿐 아니라 여러 행을 어떤 저장 묶음에 배치하느냐까지 보자.

3. 행은 저장 페이지에 함께 실린다

DB 페이지는 DBMS가 행이나 인덱스 항목을 담아 관리하는 일정 크기의 저장 묶음이고, 레코드는 그 안에 표현된 한 행의 저장 형태다. 운영체제의 파일 블록, 메모리의 페이지와 이름·크기가 우연히 같아도 책임 범위가 같다는 뜻은 아니다. 이 절의 페이지는 DB 저장 페이지를 가리킨다.

페이지에는 행 값만 꽉 차는 것이 아니라 관리 정보, 행 위치를 가리키는 정보와 남겨 둔 여유공간도 들어간다. 그래서 행의 열 길이 합 × 행 수는 출발점일 뿐 실제 파일 크기의 완성 계산이 아니다. PostgreSQL 18의 기본적인 페이지는 보통 8KiB이지만 빌드 조건 등으로 달라질 수 있으므로 모든 DBMS의 고정값으로 외우지 않는다. 1KiB는 1,024바이트다.

힙(heap) 형태의 테이블 배치는 행을 특정 키 순서로 계속 유지하지 않는 저장 방식이다. 여기의 힙은 자료구조 과목의 우선순위 힙과 다른 뜻이다. 행을 찾는 인덱스 순서와 원본 행의 실제 배치는 별개일 수 있다. DBMS의 상세 버퍼·동시성·복구 과정은 다음 장에서 다루고, 여기서는 배치가 읽을 페이지 수와 갱신 공간에 주는 영향에 집중한다.

계산 예: 100바이트 행은 8KiB 페이지에 81개씩 들어갈까

계산을 읽기 위한 가상 조건을 정한다. 페이지 크기는 8,192바이트, 페이지마다 관리영역은 192바이트, 레코드 하나의 값·행 관리정보·행 위치정보를 합한 평균은 100바이트다. 실제 특정 제품의 머리 길이나 행 배치를 그대로 복제한 수치가 아니다.

계산결과의미
8,192 − 1928,000바이트행을 담을 수 있는 계산상 영역
8,000 ÷ 10080행이 가정에서 여유 없이 채운 상한
8,000 × 0.8 ÷ 10064행행 영역의 20%를 여유로 남긴 계획
1,095,000 ÷ 6417,109.375페이지실제 할당은 올림 필요
17,110 × 8,192140,165,120바이트이 가정의 주문항목 본체 예상

페이지를 소수점만큼 배정할 수는 없으므로 17,110페이지가 된다. 약 133.67MiB이며 1MiB는 1,048,576바이트다. 아직 다른 테이블·인덱스·복구 기록·백업은 포함하지 않았다.

여유를 남기면 같은 행 수에 필요한 페이지는 늘지만 행이 커질 때 사용할 공간을 둘 수 있다. 변경이 많은지, 여유가 어떤 방식으로 재사용되는지는 DBMS의 갱신 구조에 따라 다르다. 모든 페이지를 80%만 쓰면 항상 빠르다는 규칙도, 평균 행 크기 100바이트가 모든 실제 행의 길이라는 주장도 아니다.

같은 행 수를 더 여유 있게 배치하면

자체 연습. 위의 페이지 8,192바이트·관리영역 192바이트·평균 행 100바이트·1,095,000행을 그대로 쓴다. 행 영역의 계획 점유만 80%에서 75%로 낮추면 페이지당 행 수, 필요한 페이지 수, 본체 바이트 수는 각각 얼마인가? 추가 페이지가 생기는 이유도 한 문장으로 적는다. 이 변형은 원래 계획을 변경하라는 권고가 아니다.

계산 단계와 틀린 분모 교정 보기

행 영역은 여전히 8,192−192=8,000바이트다. 여기에 75%를 적용하면 8,000×0.75÷100=60행/페이지이고, 1,095,000÷60=18,250페이지다. 본체는 18,250×8,192=149,504,000바이트이며 원래 17,110페이지보다 1,140페이지 늘어난다. 한 페이지의 여유를 늘려 같은 행 수를 담는 밀도가 낮아졌기 때문이다.

전체 8,192바이트에 바로 75%를 곱하는 답은 관리영역까지 행 공간으로 센 것이다. 행 수를 75%로 줄이는 답은 보존할 자료 자체를 바꾼 것이다. 원래 계산의 영역과 올림으로 돌아가 분모는 페이지당 허용 행 수, 분자는 보존할 전체 행 수로 나누어 고친다. 이 계산 역시 인덱스·로그·임시·백업 공간을 포함하지 않는다.

적은 행을 반환해도 많은 페이지를 읽을 수 있다

한 페이지에 관련 행이 모여 있으면 적은 페이지로 읽을 수 있지만, 같은 수의 행이 여러 페이지에 흩어져 있으면 더 많이 오간다. 고객 주문 20건을 반환했다는 결과만으로 20번의 저장장치 읽기라고 계산하지 않는다. 인덱스 페이지·원본 페이지, 이미 메모리에 있는 페이지와 장치에서 새로 읽은 페이지가 다르기 때문이다.

주소·설명처럼 긴 열을 무조건 모든 조회에 포함하면 전달량과 메모리 사용이 늘 수 있다. 빈번한 목록에 필요한 열만 읽는 후보와, 상세에서만 필요한 큰 값을 별도로 다루는 후보를 비교한다. 다만 같은 사실을 여러 표로 잘랐을 때 생기는 결합·변경·무결성 비용도 함께 검증한다. 논리적 정규화와 물리적 길이 조정은 같은 판단이 아니다.

이 부분의 출처와 가정

자료형·정밀도·문자 길이·시간대·페이지의 제품별 사실은 PostgreSQL 18 공식 문서의 수치형, 문자형, 콜레이션, 날짜와 시각, DB 페이지 배치의 확인한 부분을 독립적으로 풀어 썼다. 확인일은 2026-09-05이다.

키 순서를 유지하지 않는 힙의 경계는 Microsoft SQL Server 힙 설명의 저장 순서 설명도 대조했다. 제품마다 갱신·행 이동 구현이 달라 그 상세 동작을 일반 DBMS의 의무로 확대하지 않는다.

문구점 업무량, 페이지 관리영역 192바이트와 평균 레코드 100바이트, 80% 계획 점유는 계산을 위한 자체 가정이다. 제품의 실제 페이지 도식·필드표를 옮기거나 실측 결과처럼 표시하지 않았다. 출처 보존·장부 등록과 독립 사람 검토는 별도 검사 대상이다.

질의가 원하는 결과를 지정한다면 인덱스는 그 결과로 가는 보조 경로였고, 방금 본 DB 페이지는 행과 접근 정보를 담는 저장 묶음이었다(데이터베이스 관리시스템(DBMS)·질의·인덱스). 트리는 계층을 따라 연결을 좁히고 해시는 키를 계산된 위치에 대응시켰다(배열·연결·스택·큐·트리·그래프·해시). 두 구조를 페이지 단위의 경로로 만들었을 때 어떤 검색을 줄이고 어떤 유지 비용을 더하는지 살펴본다.

4. 원하는 행까지의 경로를 사용 방식에 맞춘다

물리 인덱스 접근경로 설계는 질의의 동등·범위·정렬·출력 요구와 데이터 분포를 인덱스 구조·열 순서·포함 범위에 대응시키고 쓰기·공간 비용으로 검증하는 일이다. 인덱스 자체의 정의는 데이터베이스 관리시스템(DBMS)·질의·인덱스 절을 참조한다. 여기서는 어떤 구조가 왜 후보인지 판단한다.

B+ 트리 계열의 인덱스는 여러 갈래의 범위 안내를 따라 내려가 정렬된 말단 항목을 찾는 균형 트리 구조다. 시작점은 루트, 마지막 층은 리프라고 부른다. 상위 페이지는 어느 값 범위로 갈지 안내하고 리프는 행을 찾을 정보 또는 저장 방식에 따라 행 자체를 담는다. 범위 시작을 찾은 뒤 이웃한 값들을 읽을 수 있어 동등 비교뿐 아니라 범위·정렬 요구에 맞는다. 제품 문서의 B-tree라는 이름을 모든 구현이 동일한 세부 구조라는 뜻으로 읽지는 않는다.

해시 인덱스는 검색 값을 해시 계산으로 저장 구획에 대응시키는 접근 구조다. 같은 값을 찾는 동등 검색이 주된 용도이고 값의 크기 순서를 보존하지 않으므로 이 구조만으로 최근 시각 순의 범위 조회를 대신할 수 없다. 서로 다른 값이 같은 구획에 갈 수 있어 일치 여부를 확인하는 과정과 분포·관리 비용도 필요하다.

나무 그림은 값을 보관하는 위치와 안내하는 위치를 나누어 읽는다

설명용 검색키를 고객번호·주문시각이라고 하자. 루트의 안내를 통해 C1이 들어 있는 값 범위의 하위 페이지로 내려가고, 말단에서 C1의 주문들을 시각 순서대로 찾는다. C1이 아닌 고객의 모든 행을 하나씩 조사하는 것과 다르다.

위치담긴 것하는 일
루트·중간 페이지아래 페이지가 맡는 값 범위와 위치갈 경로를 좁힘
리프 페이지정렬된 검색키와 행을 찾을 정보일치 항목·범위를 찾음
별도 원본 페이지가 있는 방식실제 주문 행인덱스에 없는 열을 읽음

인덱스 높이가 작다는 사실만으로 저장장치 읽기 횟수가 결정되지는 않는다. 위쪽 페이지가 메모리에 남아 있을 수 있고, 많은 리프·원본 페이지를 추가로 읽을 수도 있다. 새 값이 들어갈 페이지에 공간이 부족하면 항목을 나누는 페이지 분할 등 유지 작업이 생길 수 있으므로 읽기 경로와 쓰기 비용을 함께 본다.

고객을 먼저 모은 뒤 그 안에서 최신 주문을 찾는다

복합 인덱스는 둘 이상의 열을 정해진 순서로 묶은 인덱스다. 인덱스 키는 그 경로에서 검색·정렬 기준으로 사용하는 열 또는 식이다. 논리모델의 후보키와 이름이 비슷하지만 비유일 인덱스 키는 행을 유일하게 식별할 필요가 없다.

문구점 목록의 후보를 (고객번호 오름차순, 주문시각 내림차순, 주문번호 내림차순)으로 놓는다. 마지막 주문번호는 같은 시각의 두 주문도 일정한 순서로 표시하려는 보조 기준이다. 아래 추가 주문과 세부 시각은 정렬을 설명하는 가정이며 O101·O102의 원래 배송지·단가 규칙을 바꾸지 않는다.

고객번호주문시각주문번호
C109-03 10:00O104
C109-03 10:00O102
C109-01 09:00O101
C209-04 11:00O201
C209-02 14:00O200

C1의 9월 2일 이후 주문이라면 C1 범위 안에서 O104·O102 두 건을 순서대로 고를 수 있다. C2의 더 최신 주문 O201은 결과에 섞지 않는다. 고객 동등 조건으로 앞 범위를 정하고 시각 범위·정렬을 적용하는 이유다.

SQL 문장의 AND 조건을 앞뒤로 적는 순서와 인덱스 열의 정의 순서는 다른 문제다. 값 종류가 많은 열이면 무조건 선두가 아니라 반복되는 질의 조합과 범위·정렬을 함께 맞춘다. 선두 조건이 없으면 언제나 사용 불가라고도 쓰지 않는다. PostgreSQL 18에는 앞 열의 가능한 값을 바꾸며 반복 탐색해 필요한 범위를 찾는 스킵 스캔(skip scan)이라는 최적화가 있지만 이득 여부는 분포와 비용에 따라 달라진다.

드물게 나오는 값과 자주 나오는 값은 같은 인덱스에서도 다르다

이 절에서 선택도(selectivity)는 전체 후보 행 중 조건에 맞는 행의 비율이다. 말로 높다·낮다고 외우기보다 100만 행 중 100행=0.01%처럼 분모와 분자를 적는다. 값의 종류 수가 많다는 사실과 한 특정 값이 적게 나온다는 사실도 같지 않다.

설명용 100만 행에서 C1이 100행, C2가 40만 행을 가진다면 고객번호 조건이라는 문장 모양이 같아도 읽을 양이 크게 다르다. 적은 행은 인덱스를 따라 찾아가는 후보가 유리할 수 있고, 많은 행은 원본 페이지를 순차적으로 읽는 편이 더 쌀 수 있다. 고객별 분포가 고르다는 평균 가정만으로 선택하지 않는다.

주문 목록용 인덱스 한 개는 읽기를 줄일 수 있지만 새 주문마다 항목이 추가되고 키 값 변경 때 유지 작업도 생긴다. 출력 열까지 넓게 넣으면 조회의 원본 접근을 줄이는 대신 인덱스 자체가 커진다. 읽기 지연·쓰기에 드는 시간·공간·유지 시간을 같은 측정표에서 비교한다.

전체 열에 보통 인덱스를 하나씩 만드는 것 외에도 선택이 있다

선택의미와 맞는 상황비용·실패 경계
커버링 인덱스(covering index)특정 질의에 필요한 열을 인덱스 안에 포함해 원본 접근을 줄이는 설계넓어진 공간·쓰기 비용, 제품의 추가 원본 확인 가능성
식 기반 인덱스(expression index)열에 함수를 적용한 결과를 저장해 같은 식의 검색을 지원식 계산·갱신 비용, 질의 식과 정의의 일치 확인
부분 인덱스(partial index)정한 조건을 만족하는 행만 인덱싱질의 조건이 해당 부분의 범위 안에 있음을 DBMS가 판단해야 함
비트맵 인덱스(bitmap index)값별로 해당 행 여부를 비트열에 나타내 조합 조건을 처리분석 중심 후보, 변경·경합 특성은 제품에서 검증

예컨대 작성중 주문만 찾는 업무에는 상태=작성중인 부분 인덱스를 검토할 수 있다. 취소·확정을 포함한 전체 이력을 이 인덱스만으로 읽을 수 있다는 뜻은 아니다. 상품코드를 소문자로 바꿔 검색하는 업무라면 일반 코드 인덱스가 아니라 그 식을 지원하는지 확인한다. 대소문자 통합 자체가 업무 규칙에 맞는지도 앞의 도메인 계약으로 검증한다.

PostgreSQL 18에서 필요한 열을 모두 포함했다고 실제 원본 접근이 반드시 0이 되지는 않는다. 현재 트랜잭션이 그 행을 볼 수 있는지 확인할 조건 때문에 원본 페이지를 방문할 수 있다. 이 확인의 내부 구조는 다음 DBMS 장에서 다룬다. 비트맵도 Oracle의 저장 인덱스와 PostgreSQL 실행계획에서 행 위치를 모으는 비트맵 접근을 같은 저장 구조라고 혼동하지 않는다.

묶어 저장하는 방식은 제품 이름과 읽는 방향을 구분한다

클러스터드 배치라는 말은 관련 키의 행을 가깝게 조직해 읽기 지역성을 높이는 저장 선택을 가리키지만, 구체 보장은 제품마다 다르다. SQL Server의 행 저장형 클러스터드 인덱스는 말단에 데이터 행을 두는 구조다. PostgreSQL의 CLUSTER는 선택한 인덱스 순서로 한 번 재배치하며 이후 변경이 그 순서를 계속 유지해 준다는 보장은 아니다.

행 저장(rowstore)은 한 행의 여러 열을 함께 조직하고, 열 저장(columnstore)은 같은 열의 값들을 모아 조직하는 방식이다. 주문 한 건의 상세를 자주 읽고 바꾸는 요구와, 수많은 주문에서 날짜·금액 두 열만 집계하는 요구는 읽는 방향이 다르다. 열 저장은 필요한 열만 읽고 비슷한 값들을 압축하는 이점을 검토하지만, 변경 반영·혼합 조회와 운영 비용도 제품별로 확인한다.

배치를 바꿔도 결과 순서는 질의에 정렬 요구를 명시한다. 저장 때의 우연한 순서를 최근 주문 순서로 믿지 않는다. 원본 한 구조에 모든 업무를 억지로 맞출지, 정합성·허용 지연을 정한 조회용 구조를 별도로 둘지는 다음의 비정규화 판단과 연결된다.

문구점의 인덱스 후보를 채택·보류 이유로 기록한다

후보기대 이득유지해야 할 경계
주문의 주문번호 유일 경로상세 주문 1건 접근과 유일성상품·시각과 무관한 원래 주문 식별 유지
주문항목의 주문번호·항목번호 유일 경로한 주문의 항목 접근과 줄 식별같은 상품 여러 줄을 허용
주문의 고객번호·주문시각·주문번호 경로고객별 최신 목록의 검색·정렬추가 쓰기·공간, 같은 시각에 주문한 건들의 일정한 표시 순서
상태 하나만의 경로특정 희소 상태 조회의 가능성확정 상태가 대부분이면 전체 조회 이득 재검토
목록 출력 열을 포함한 넓은 경로원본 접근 감소 후보폭 증가와 쓰기·메모리 비용 측정

물리 후보표의 핵심은 인덱스 이름의 개수가 아니라 어느 요구를 만족시키고 어떤 비용이 드는지다. 유일성 보장에 쓰는 인덱스는 조회에 덜 쓰인다는 이유만으로 제거하지 않는다. 다른 제약이나 관리 기능이 의존하는지도 먼저 확인한다.

앞 절의 관계 매핑은 업무의 개체·관계를 표와 키·참조로 옮겼으며, 무결성은 그 규칙을 계속 지켜야 한다는 조건이었다(개념·논리 모델과 정규화: 뜻을 잃지 않고 표를 나눈다, 정규화·중복·무결성). 저장 부분을 나눌 때에는 값의 구간을 정하거나 앞서 배운 해시 계산으로 갈 곳을 정할 수 있다(배열·연결·스택·큐·트리·그래프·해시). 어디에 저장하든 주문번호의 유일성 같은 원래 규칙이 그대로 유지되는지 함께 확인해야 한다.

5. 큰 표를 나눌 때는 어떤 질문에서 건너뛸 수 있는지 본다

테이블 파티셔닝은 논리적으로 한 표인 데이터를 규칙에 따라 여러 저장 부분으로 나누어 관리하는 방식이다. 파티션 키는 각 행을 어느 부분에 둘지 정하는 열 또는 허용된 식이다. 여기서는 한 DB 안의 물리 배치·범위 제외·제약을 다루며 여러 서버의 복제·샤딩·재배치는 복제·파티셔닝·샤딩의 범위다. 파티션이 여러 개라고 독립 서버가 여러 대라는 뜻은 아니다.

파티션 가지치기(pruning)는 질의 조건을 만족할 행이 없다고 판단한 파티션을 읽을 대상에서 제외하는 최적화다. 필요한 파티션 안에서는 인덱스 또는 전체 읽기를 다시 선택할 수 있다. 파티션을 나누는 것과 인덱스를 만드는 것은 같은 최적화가 아니다.

범위 분할은 날짜 구간처럼 값의 범위로, 목록 분할은 지역 코드처럼 정한 값 묶음으로, 해시 분할은 키의 해시 결과로 나눈다. 둘 이상을 겹친 복합 분할도 가능하지만 분할 수·관리 대상과 제한사항이 늘어난다. 어떤 방법이든 질의 조건·행의 쏠림·수명주기와 제품의 제약을 함께 본다.

9월 데이터만 묻는다면 8월과 10월을 제외할 수 있다

주문시각으로 월별 분할하는 후보를 살펴보자. 날짜 경계는 앞에서 합의한 같은 시간 기준을 사용한다. 아래 시작 이상·끝 미만 규칙은 경계 시각이 두 파티션에 동시에 들어가는 오류를 막는다.

파티션시작 이상끝 미만
8월2026-08-01 00:002026-09-01 00:00
9월2026-09-01 00:002026-10-01 00:00
10월2026-10-01 00:002026-11-01 00:00

9월 1일 00:00 주문은 9월에, 10월 1일 00:00 주문은 10월에 들어간다. 9월 주문만 조회하면 8월·10월에 답이 없다고 확인해 제외하는 후보가 된다. 반대로 날짜 조건 없이 주문번호 하나만 묻는다면 날짜 분할만으로 대상 월을 알 수 없어 여러 부분을 확인할 수 있다.

최근 90일은 달력의 정확히 세 달과 같지 않아 월 경계에 따라 네 파티션에 걸칠 수도 있다. 세 달 분할=항상 3개만 읽음이라고 단정하지 않는다. 질의가 실제 읽은 파티션을 실행계획에서 확인해야 한다.

나누는 기준 때문에 원래의 유일성이 약해질 수 있다

PostgreSQL 18에서 파티션 테이블에 기본키·유일 제약을 만들 때는 파티션 키 열을 제약 열에 포함해야 하는 등의 제한이 있다. 각 부분 안에서만 검사하는 유일성으로는 서로 다른 부분의 같은 번호를 막을 수 없기 때문이다.

문구점의 주문번호는 전체에서 유일이라는 규칙을 유지해야 한다. 월 분할을 위해 키를 주문시각·주문번호로 바꾸면 다른 시각에 같은 주문번호가 다시 들어오는 것을 그 복합키만으로 막지 못한다. 편의를 위해 논리 규칙을 약화시키지 말고, 비분할 주문 원본 유지 같은 다른 물리 후보를 먼저 비교한다. 분할을 채택하려면 전체 유일성·참조를 보장하는 구조와 검증 책임을 별도로 설계해야 한다.

위험실패 예확인할 통제
미래 파티션 준비 누락다음 달 입력이 갈 곳이 없음생성 책임·사전 점검·경계 시험
값의 쏠림한 날짜·고객으로 쓰기가 집중실제 분포·경합·키 후보 비교
너무 많은 작은 분할계획·관리 대상이 급증건수와 계획시간·운영비 측정
날짜 조건이 맞지 않음모든 파티션을 읽음가지치기 가능한 조건과 실제 계획
보존 판단 없는 분리·삭제필요한 거래·감사 데이터 손실보존 근거·예외·복원검증 후 처리

파티션을 떼어 내는 기능이 빠르다는 사실과 해당 데이터를 지금 폐기할 권리가 있다는 판단도 별개다. 교재 사례에서는 실제 삭제 명령을 실행하지 않는다.

파티션의 이득이 작으면 나누지 않는 것도 설계다

현재 규모에서 고객별 최근 주문 인덱스로 요구를 만족하고 보관·운영도 감당된다면, 월별 분할이 추가 복잡성만 만들 수 있다. 반대로 매우 큰 기간별 데이터에서 오래된 부분의 보관·제외가 반복된다면 분할 후보의 가치가 커진다. 특정 행 수를 넘으면 언제나 파티셔닝한다는 보편 임계값은 없다.

문구점에서는 전체 주문번호 유일성과 항목의 참조를 단순하게 유지하는 비분할 원본을 기준안으로 삼고, 날짜 분할은 월별 조회·보관 이득과 제약 보완 비용을 측정한 뒤 채택한다. 이 결론은 분할 기능이 나쁘다는 뜻이 아니라 현재 요구에 대한 선택이다.

6. 중복을 둘 때는 무엇이 원본인지 먼저 적는다

정규화·비정규화의 정의는 정규화·중복·무결성, 주문 사례의 이력 보존·반정규화 경계는 앞 절의 개념·논리 모델과 정규화에서 설명했다. 물리 설계에서는 먼저 질의·인덱스·반환량을 검토하고 실제로 남은 읽기 비용 때문에 중복이 필요한지 판단한다. 주문 O101의 확정단가와 배송지는 다른 시점의 원천 사실이지, 현재가격·현재주소의 단순한 조회용 복제가 아니다.

문구점 목록에 주문 합계를 저장해 매번 항목을 합산하지 않는 후보를 택한다면, 기준은 주문항목의 확정단가×수량 합이다. 작성중 항목 변경과 확정·취소 때 합계를 어떻게 갱신할지 정하고, 원본 합과 저장 합의 불일치를 탐지해 다시 계산할 수 있어야 한다. 확정 후 원수량·원단가를 보존하는 규칙도 유지한다.

선택얻는 것책임
조회할 때 원본 항목 합산중복값 갱신 불필요조회 비용을 측정·최적화
같은 업무 변경에서 저장 합계 갱신즉시 읽기 간소화함께 반영·취소되는 경계와 동시성 통제
지연을 허용한 조회용 요약분석 조회를 원본과 분리허용 지연 표시·갱신 실패 탐지·재생성

저장 합계를 만드는 것과 모든 고객·상품 정보를 주문에 복사하는 것은 다른 선택이다. 필요하지 않은 중복을 늘리지 않고 읽기 이득, 갱신 경로, 일관성 수준과 복구 책임을 비교한 결정만 남긴다.

페이지에는 실제 행뿐 아니라 관리 정보와 여유도 들어갔으며, 이 크기는 바이트와 그 배수 단위로 맞춰 계산했다. 측정값을 비교하려면 대상·기간·단위와 기준 조건을 먼저 정해야 했다(측정값·지표·목표·기준선). 이제 같은 원리로 저장 위치마다 무엇이 얼마나 오래, 동시에 존재하는지 합산한다.

7. 용량은 테이블 파일 하나의 크기로 끝나지 않는다

물리 DB 용량 산정은 계획기간의 행 수·실제 행 크기·저장 밀도로 데이터와 인덱스 크기를 예측하고, 복구 기록·임시 작업·백업·운영 여유를 저장 위치별로 더하는 작업이다. 같은 바이트를 두 번 세거나 다른 위치의 비용을 빠뜨리지 않도록 계산 범위를 명시한다.

앞의 주문항목 1,095,000행 예는 본체만 약 133.67MiB였다. 나머지 테이블과 각 인덱스는 자기 행·항목 길이와 관리공간으로 따로 산정해야 한다. 복구 기록은 변경을 장애 뒤 재현하는 데 필요한 기록이고, 임시 공간은 정렬·인덱스 생성 같은 진행 중 작업이 잠시 쓰는 영역이다. 생성·보존·정리 방식의 세부 이론은 DBMS 복구를 다루는 절로 이어진다.

페이지 안에 남긴 여유는 행 배치의 여유이고 저장 볼륨 전체에 남긴 여유는 로그 증가·재구성·예측 오차를 감당할 공간이다. 둘의 목적과 계산 위치를 나누어 적는다. 읽기 장치의 처리량과 지연도 저장 바이트 수만으로 결정되지 않는다.

계산 예: 본체 134MiB인 표에 134MiB 디스크만 주면 부족하다

아래는 계획기간 말의 가상 산정표다. 주문항목 본체 133.67MiB는 앞의 페이지 계산을 재사용하며, 나머지는 예제용 추정값이다. 제품에서 측정한 값이 아니다.

같은 운영 저장 위치의 항목계획량
주문항목 본체133.67MiB
주문 등 나머지 테이블100MiB
인덱스 전체90MiB
데이터·인덱스 소계 올림324MiB
이 위치에 보존할 복구 기록256MiB
동시에 필요할 임시 작업 최대128MiB
최대 사용량 가정 합계708MiB

저장 위치의 계획 최대 점유를 70%로 제한한다는 가정을 추가하면 필요한 전체 공간은 708÷0.70 ≈ 1,011.43MiB이므로 1MiB 단위 계획에서는 최소 1,012MiB로 올린다. 사용량에 30%를 더한 708×1.3=920.4MiB는 같은 계산이 아니다. 920.4MiB 중 708MiB는 약 76.92%이기 때문이다.

백업을 다른 위치에 둔다면 그 위치의 보존 세대·압축·복구 기록을 별도로 계산한다. 운영 위치의 1,012MiB에 자동 포함되었다고 하지 않는다. 재구성 작업이 기존 구조와 새 구조를 동시에 요구하면 그 순간의 최대 공간도 검증한다. 숫자의 목표는 특정 여유율 암기가 아니라 어느 위치에서 무엇이 동시에 존재하는가를 묻는 것이다.

일부 조건만 바꾸어 계산하기. 다른 항목과 최대 점유율은 그대로 두고, 같은 운영 위치에 보존할 복구 기록만 256MiB에서 512MiB로 늘었다면 필요한 전체 공간은 얼마인가? 먼저 표에서 바뀐 행 하나를 찾아 소계를 고친 뒤 전체 공간을 구한다.

먼저 계산한 뒤 용량 산정 해설 보기

해설과 교정. 데이터·인덱스 324MiB와 임시 128MiB는 변하지 않았으므로 새 최대 사용량은 324+512+128=964MiB다. 전체 공간은 964÷0.70≈1,377.14MiB이므로 1MiB 단위에서는 최소 1,378MiB다. 기존 1,012MiB에 증가분 256MiB만 더한 1,268MiB를 택하면 점유율이 964÷1,268≈76.0%여서 70% 조건을 어긴다. 사용량의 증가와 전체 공간의 증가를 같게 읽었다면 위 소계→점유율→올림의 순서로 돌아가 고친다. 이 계산은 복구 기록의 저장공간만 바꾼 가정이며 장애 복구시간이 두 배가 된다는 뜻은 아니다.

저장 위치와 큰 값의 처리도 운영 결정이다

테이블스페이스(tablespace)는 DB 객체의 저장 위치를 관리하는 논리적 단위다. PostgreSQL 18에서는 파일시스템의 특정 위치에 연결해 테이블·인덱스 등을 배치할 수 있다. 논리 이름을 나눴다고 물리 장치·전원·장애영역까지 분리된 것은 아니므로 실제 경로와 장치 의존성을 확인한다.

큰 설명문·첨부값은 행 안에 전부 담기 어려울 수 있다. PostgreSQL은 큰 속성값을 압축하거나 행 밖에 저장하는 기법을 사용한다. 여기서는 큰 값의 별도 저장 때문에 추가 공간·접근이 생길 수 있다는 경계만 사용한다. 제품의 임계값과 내부 분할 조각 구조를 다른 DBMS까지 일반화하지 않는다.

압축은 공간과 전송량을 줄이는 대신 압축·해제의 연산 비용을 낼 수 있다. 자동 증가 기능도 장치의 실제 여유를 만들지는 않는다. 파일·복구 기록·임시 공간의 증가 알림, 정리 작업의 책임, 접근권한과 백업·복원 범위를 배치안에 함께 둔다. 백업 파일이 있다는 사실만으로 복구가 성공한다고 보지 않는다.

물리 설계는 논리적 뜻을 유지하면서 저장·접근·운영의 후보를 정하는 일이었고, 인덱스 후보마다 읽기를 줄이는 효과와 쓰기·공간의 추가 비용이 달랐다. 좋은 숫자 하나가 아니라 같은 대상·기간·조건의 측정값과 수용기준을 비교해야 한다는 원칙을 여기에도 적용한다(측정값·지표·목표·기준선). 주문이 정확히 처리되면서 읽기·쓰기·복구 요구도 충족하는지 확인할 차례다.

8. 예상한 경로와 실제 비용을 같은 조건에서 대조한다

물리 설계 검증은 동일한 데이터·질의·동시성·장애 조건에서 후보의 정확한 결과와 읽기·쓰기·공간·운영 비용을 측정하여 요구 충족을 판정하는 과정이다. 실행계획은 어떤 접근과 결합·정렬을 할지 보여 주지만, 예상 비용이 곧 밀리초 단위의 사용자 응답시간은 아니다.

PostgreSQL의 EXPLAIN은 선택한 실행계획과 추정치를 보여 주고, EXPLAIN ANALYZE는 질의를 실제 실행해 관측값을 덧붙이는 기능이다. 변경문을 분석하면 데이터 변경도 실제로 일어날 수 있으므로 운영 데이터에 무심코 실행하지 않는다. 이 교재의 표는 독자가 따라 실행할 실습이 아니라 이미 정리한 가상 관측 예다.

계획의 추정 행 수와 실제 행 수가 크게 다르면 오래된 통계·쏠림·열 사이 상관관계를 검토한다. 통계는 정확한 전체 데이터 복사본이 아니라 계획 선택을 위한 요약·표본 정보다. 자료와 부하가 달라지면 한 번 좋았던 인덱스도 다시 평가한다.

평균 읽기만 개선된 후보를 최종안으로 뽑지 않는다

앞의 같은 데이터 규모와 100개 동시 조회·30분 구간을 사용하되, 주문 쓰기 부하도 두 후보에 같은 방식으로 겹친 가상 결과를 보자. 쓰기 p95 100ms 이하는 이 비교 예에 추가한 가정이다.

항목기준안 A목록 열까지 넓힌 인덱스 B판단
조회 결과·순서·업무규칙일치일치정확성 선행조건 통과
목록 응답 p95280ms180ms둘 다 조회 300ms 이하
주문 쓰기 p9580ms140msB는 쓰기 100ms 기준 미달
해당 인덱스 공간20MiB65MiBB가 45MiB 더 사용
실제 원본 페이지 접근남아 있음줄었지만 남아 있음포함 열만으로 0이라고 가정하지 않음

B가 읽기만 100ms 빠르다고 전체 설계가 더 낫지는 않다. 이 가정에서는 A가 읽기·쓰기 기준을 모두 충족하므로 A를 유지하고, 추가 읽기 이득이 꼭 필요한 경우에만 다른 후보를 다시 찾는다. 이 표는 제품 성능 순위나 실측 보증이 아니다.

작은 표의 성공을 대규모로 그대로 확대하지 않고 실제 분포·대표 고객·첨두 쓰기와 함께 검증한다. 이미 메모리에 있는 데이터와 처음 읽는 데이터의 조건도 구분한다. 저장장치에서 읽은 횟수, 전체 논리 접근과 반환 행 수를 서로 다른 값으로 기록한다.

좋은 인덱스도 변경 중에는 서비스에 비용을 줄 수 있다

새 구조의 생성·자료형 변환·분할 변경은 기존 행을 읽고 새 구조를 쓰며 잠금·추가 공간을 사용할 수 있다. 변경 전에 예상 작업량, 허용 중단, 동시에 필요한 공간, 중단·되돌리기 조건과 검증 대상을 정한다. 생산자·소비자와 저장된 옛 데이터의 전환 경계는 데이터 형식·스키마·호환성의 원칙을 적용한다.

동시 인덱스 생성(concurrent index build)은 일반 쓰기를 계속 허용하면서 인덱스를 만드는 제품 기능을 뜻하지만 무부하·무대기와 같지 않다. PostgreSQL 18의 해당 방식도 추가 검사·대기를 수행하며 실패하면 질의에 쓰이지 않는 무효 인덱스가 남아 유지비용을 낼 수 있다. 유일성 검사에 미치는 영향도 확인하고 상태 점검·정리 또는 재생성 절차를 둔다.

변경 뒤에는 구조 존재만 보지 않고 제약 위반 0, 대표 질의의 결과·순서, 읽기·쓰기 응답, 실제 공간과 장애 후 복원을 확인한다. 대기시간·오류율·공간이 중단 기준을 넘으면 계획한 안전 절차로 멈추고 이전 구조·데이터의 정합성을 다시 검증한다. 제품별 명령의 정확한 잠금 범위와 버전 제한은 실행 전에 확인한다.

설계 실패를 징후와 수정 책임으로 연결한다

실패확인할 징후통제·수정
의미보다 빠른 표현 선택금액·코드·시각의 변환 오류자료형·제약과 입력 경계 재검증
모든 질의에 인덱스 추가쓰기 지연·공간·유지시간 증가요구별 기여와 의존 제약을 보고 정리
평균 분포만 가정특정 고객·기간만 느림쏠림·상관과 추정/실제 행 수 대조
분할과 유일성 충돌다른 월에 같은 주문번호 존재원래 키 규칙 유지, 분할안 재선택
파일 크기만 산정재구성·로그 증가 때 공간 부족위치별 최대 동시 사용량과 여유 재계산
중복값 갱신 누락저장 합계와 항목 합 불일치원천·동시 갱신·탐지·재생성
생성 명령 종료만 확인무효 구조·성능 악화·잠금 대기상태·결과·지연·복원까지 검증

잘못된 물리 선택 때문에 의미가 손상되었다면 속도만 되돌려서는 해결되지 않는다. 어떤 원본·변환·시점에서 값이 달라졌는지 확인하고 복구 범위와 증거를 남긴다.

요구에서 승인 가능한 검증 자료까지 이어지는 순서

  1. 논리 표·키·현재/이력·업무규칙과 물리적으로 바꾸면 안 되는 의미를 고정한다.
  2. 질의·쓰기별 조건·정렬·결과량·빈도·동시성·증가량과 성능·보존·복구 기준을 적는다.
  3. 자료형·길이·정밀도·문자 비교·시간 기준과 제약을 대응시키고 경계 입력을 검사한다.
  4. 페이지·행 배치와 인덱스의 구조·열 순서·포함 범위를 후보로 만든다.
  5. 분할의 질의 제외·보관 이득과 전체 키·참조·분포·운영 비용을 비교한다.
  6. 비정규화가 필요하면 원천·갱신 경로·허용 지연·불일치 탐지·재생성을 정한다.
  7. 테이블·인덱스·복구 기록·임시·백업의 위치별 공간과 변경 중 최대치를 계산한다.
  8. 같은 조건에서 결과·실행계획·읽기·쓰기·공간·복원을 검증하고 선택·기각 이유와 변경 절차를 남긴다.

이 순서는 앞의 제품 원리와 업무 검증을 묶은 편집상 종합이다. 특정 표준이 모든 단계와 임계값을 의무화한 것으로 표시하지 않는다.

물리 설계의 답안은 하나의 인덱스보다 넓다

전체 물리 설계의 답안은 논리모델·업무 요구에서 실제 자료형·저장·접근·분할·용량·검증으로 이어지는 인과를 보여 준다. 물리 설계의 입력·산출물, 행과 페이지·인덱스의 작동, 읽기·쓰기·정확성·공간의 비교, 실패·변경·복원 통제를 함께 묶는다.

복합 인덱스만 정확하게 설명한 것은 접근경로의 부분 증거이고, 파티션만 나열한 것은 분할의 부분 증거다. 25점 통합문제에서는 유지할 업무규칙을 시작점으로 각 선택의 근거와 검증 결과까지 연결한다.

9. 기출의 개별 논점을 통합 선택으로 바꾼다

기존 원문 후보 장부에는 69회 2교시 3번의 물리 설계 관점 인덱스 선택, 95회 1교시 6번의 인덱스 종류, 136회 2교시 5번의 클러스터드·논클러스터드 비교가 있다. 83회 4교시 4번과 135회 2교시 1번은 비정규화 기준·절차·유형의 관련 후보다. 여기서는 원문 전체를 전재하지 않고 이 절에서 배운 선택축에 연결한다.

127회 4교시 3번의 샤딩과 파티셔닝 비교는 이 절의 단일 DB 분할만으로 전체가 끝나지 않는다. 노드 분산과 복제·재배치는 다음 장의 이론이 필요하다. 95회 3교시 6번의 SQL 재작성과 111회 4교시 3번의 공간 인덱스 세부도 현재 일반 인덱스 설명만으로 완전히 해설했다고 표시하지 않는다.

자동 장부의 과거 분류·현행성은 승인 결과가 아니다. 제품별 구조와 제약은 확인한 버전 근거로 다시 설명하고 원문·범위·권리의 독립 사람 검토는 남겨 둔다.

10. 10점 전환: 질의에서 인덱스 선택으로

복합 인덱스의 열 순서 선정 원리와 읽기·쓰기·공간의 교환관계를 설명하고, 고객별 최근 주문 조회에 대한 선정·검증방안을 제시하시오.

검색 구조의 이름만 나열하지 않는다. 고객 동등 조건과 시각 범위·정렬, 같은 시각의 보조 순서, 데이터 쏠림·쓰기 비용과 실제 검증을 연결한다. 이 문제는 물리 설계 전체가 아니라 접근경로 설계의 부분 문제다.

인덱스 선택 풀이 보기

답안 목차

  1. 인덱스 역할과 물리 접근경로 선정 목적
  2. 고객 동등·시각 범위·정렬에 맞춘 복합 열 순서
  3. 선택 비율·쏠림과 전체 읽기의 비교
  4. 포함 열과 인덱스 유지의 읽기·쓰기·공간 비용
  5. 동일 조건의 결과·계획·지연·공간 검증

답안 도식

본문의 복합 인덱스 정렬 예를 다음 순서로 읽는다. 고객 동등조건으로 범위를 좁힌 뒤 시각 범위·정렬을 적용하고, 주문번호로 동률 순서를 정한다.

비교할 접근 후보함께 측정할 근거선택의 증거
복합 인덱스 후보분포·반환비율, 쓰기·공간·유지비같은 조건의 결과·실행계획·지연
전체 읽기 후보같은 분포·반환비율과 부하결과의 값·순서를 유지한 비용 비교

앞의 업무의 뜻을 지킨 후보만 채택한다 그림에서처럼 검증 뒤 채택하거나 후보를 수정한다.

10점 모범답안

인덱스는 특정 값에서 행을 찾는 보조 구조이며, 접근경로 설계는 질의의 조건·정렬·출력 요구를 구조와 열 순서에 맞추는 작업이다.

고객별 최근 주문은 고객번호 동등 조건을 선두로 좁히고 주문시각 내림차순과 주문번호 보조 순서를 둔 복합 인덱스를 후보로 한다. SQL 조건을 쓰는 문장 순서와 인덱스 정의 순서는 구분한다.

조건의 선택 비율과 고객별 쏠림을 확인하고, 많은 행을 읽는 경우에는 전체 읽기 비용과 비교한다. 선두 조건이 없다고 언제나 사용 불가라 단정하지 않고 제품의 최적화와 계획을 확인한다.

출력 열을 포함하면 원본 접근을 줄일 수 있으나 인덱스 폭·저장·쓰기 유지비용이 늘며 제품의 추가 확인 때문에 원본 읽기가 남을 수 있다.

같은 데이터·동시성과 쓰기 부하에서 결과·순서, 추정/실제 행 수, 조회·쓰기 지연과 공간을 비교한다. 읽기만 빨라지고 쓰기 기준을 어긴 후보는 채택하지 않으며 유일성·참조 규칙에 의존하는 경로를 무분별하게 제거하지 않는다.

11. 25점 전환: 의미를 지키며 읽기·쓰기·공간을 함께 설계한다

문구점 주문 서비스는 고객별 최근 90일 주문을 최신순 20건씩 조회하며, 동시 조회 100건의 30분 시험구간에서 p95 300ms 이내가 요구된다. 하루 주문 1,000건·평균 3개 항목의 증가를 고려하여, 기존 논리모델과 업무규칙을 유지하는 물리 DB 설계와 용량·변경·검증방안을 제시하시오.

표·키·현재/이력의 규칙을 시작점으로 자료형, 저장 페이지, 인덱스, 분할, 비정규화, 용량과 검증을 연결한다. 계산의 가정과 실제 제품의 제약을 분리하고, 기능이 가능하다는 사실을 곧바로 최종 선택으로 쓰지 않는다.

통합 물리 설계 풀이 보기

답안 목차

  1. 논리모델·업무규칙과 사용량·성능의 입력 고정
  2. 자료형·정밀도·문자 비교·시간·제약 선택
  3. 행·페이지와 저장 배치의 비용
  4. 고객별 최신 조회의 인덱스·분포·쓰기 비용
  5. 파티션의 가지치기 이득과 전체 유일성 경계
  6. 비정규화의 원천·갱신·검증 책임
  7. 위치별 데이터·인덱스·로그·임시·백업 용량
  8. 변경 중 안전과 동일 조건의 결과·성능·복원 검증
  9. 요구→물리 후보→비용→검증의 통합 결론

답안 도식

앞의 업무의 뜻을 지킨 후보만 채택한다 그림을 통합 답안의 지도에 사용한다. 입력은 업무규칙·논리모델과 질의·쓰기·성능·증가·보존 요구다.

같은 입력에서 비교할 선택축검증 전에 합칠 근거
자료형·제약표현·업무규칙의 정확성
행·페이지·인덱스저장·읽기·쓰기 비용
분할·조회용 중복제외·보관 이득, 원천·갱신 책임

세 축의 선택을 위치별 용량과 변경 중 최대 공간에 반영한다. 결과·계획·읽기·쓰기·복원을 검증한 뒤 모든 기준을 충족하면 채택하고, 미달이면 후보와 가정을 수정한다.

25점 모범답안

물리 DB 설계는 논리적 의미와 제약을 제품의 자료형·저장·접근·분할·용량과 운영 선택으로 구현하는 과정이다. 고객·상품·주문·주문항목, 주문번호의 전체 유일성, 항목번호로 같은 상품 여러 줄을 구별하는 규칙과 확정단가·배송지의 과거 사실을 유지한다. 최근 90일·최신 20건·동시 100건·30분 p95 300ms 조건과 쓰기·보존·복구 요구를 입력으로 고정한다.

원 단위 금액은 정확한 정수·십진수형과 합계까지의 범위로 선택하고 반올림 허용 여부를 검사한다. 문자 길이와 인코딩·대소문자·공백 비교를 구분하며, 주문 사건 시각과 월 경계의 시간 기준을 맞춘다. 필수·값 범위·키·참조와 여러 행에 걸친 업무규칙도 제품 제약과 처리 경계로 구현한다.

저장 행에는 값 외 관리정보가 있고 페이지에도 관리·여유공간이 있다. 행이 흩어진 정도와 필요한 열의 폭을 고려하며 행 저장·열 저장·키 기반 배치의 이득과 갱신비용을 제품별로 판단한다. 기본키나 일회성 재배치가 계속된 물리 정렬을 보장한다고 가정하지 않는다.

목록에는 고객번호·주문시각·주문번호 순의 복합 인덱스를 후보로 하여 동등 범위와 최신·동률 순서를 맞춘다. 상세와 항목은 원래 유일 키 경로를 유지한다. 선택 비율·쏠림·출력 열을 분석하고 넓은 커버링 후보의 읽기 이득과 쓰기·공간 비용을 전체 읽기와 비교한다.

월별 분할은 날짜 조건으로 불필요한 월을 제외하고 보관을 단순화하는 후보지만, 최근 90일이 항상 세 파티션은 아니다. 주문번호만의 조회와 전체 유일성·항목 참조를 검토한다. PostgreSQL 18처럼 분할키를 유일 제약에 포함해야 하는 제한을 확인하고 원래 주문번호 규칙을 약화시키지 않는다. 현재 요구를 충족하면 비분할 원본을 유지하는 안도 채택한다.

저장 합계가 필요하면 주문항목을 원천으로 하고 작성중 변경·확정·취소의 갱신 경계를 정한다. 지연을 허용한 요약은 지연 표시·실패 탐지·재생성 책임을 둔다. 과거 확정단가·배송지를 현재값의 단순 복제로 오인하지 않는다.

하루 1,000주문×3항목×365일은 항목 1,095,000행이다. 페이지당 64행의 가상 조건에서는 17,110페이지가 필요하다. 데이터·인덱스 324MiB, 복구 기록 256MiB, 임시 128MiB가 같은 위치에 동시에 필요하고 최대 점유 70%라면 708÷0.70을 올림한 1,012MiB를 계획한다. 별도 백업 위치와 변경 중 신·구 구조의 동시 공간은 따로 산정한다.

변경은 잠금·공간·중단 기준과 되돌리기·복구 절차를 정하고, 생성 완료 뒤 유효 상태와 제약·결과·순서를 확인한다. 실행계획의 추정치를 실측 지연으로 오인하지 않고 같은 분포·동시성·쓰기 부하에서 조회·쓰기 p95·페이지 접근·공간과 복원을 검증한다. 읽기만 개선되고 쓰기 기준을 어기는 후보는 수정한다.

결론은 요구를 물리 후보와 비용·실패 통제·검증에 연결한 선택표로 남긴다. 기능 이름이나 최고 읽기 속도가 아니라 원래 의미와 모든 수용기준을 만족하는 가장 단순한 물리안을 채택하고, 데이터 증가·분포와 제품 버전이 변하면 다시 평가한다.

제품별 근거와 자체 사례의 경계

인덱스는 Microsoft SQL Server 인덱스 설계 자료, PostgreSQL 18 인덱스 종류·복합 열·포함 열, Oracle 19c 인덱스 원리의 확인한 부분을 사용했다. 제품의 B-tree/B+ 트리, 저장 비트맵과 실행 중 비트맵, 계속 유지되는 구조와 일회성 배치를 구별했다.

분할·키 제한은 PostgreSQL 18 테이블 파티셔닝, 추정·실측 경계는 EXPLAIN 사용법, 변경 중 제한은 CREATE INDEX를 대조했다. 세부 식·부분 인덱스, 통계·저장 위치의 확인 범위도 장부에 별도로 연결한다. 확인일은 2026-09-05이다.

숫자·정렬 표·목차·도식·성능 비교는 직접 만든 설명용 사례이며 실제 시험 결과나 특정 표준의 보편 임계값이 아니다. 최신 기능·제한과 제품 판은 배포 전에 다시 확인하며, source 보존·권리·외부 기술사·초보 독자 검증을 실제 수행한 것처럼 표시하지 않는다.

다시 읽을 때 붙잡을 한 줄

논리모델의 뜻은 지키고 무엇을 얼마나 읽고 쓰는가를 자료형·행·인덱스·분할·용량의 선택으로 바꾼다. 선택마다 읽기 이득뿐 아니라 쓰기·공간·무결성·변경·복구 비용을 적는다. 마지막 판정은 기능의 존재가 아니라 같은 조건의 결과와 모든 수용기준이다.

이 페이지 목차

이 페이지 목차

0. 표가 올바른 것과 빨리 안전하게 읽히는 것은 다른 문제다1. 물리 설계는 요구를 실제 저장·접근·운영 선택으로 바꾼다전체 지도: 바꾸지 않을 뜻에서 검증할 결과까지같은 문구점 사례에 사용량과 측정 범위를 붙인다표 이름보다 먼저 바꾸면 안 되는 사실을 고정한다2. 열의 뜻을 자료형·길이·비교 규칙으로 구현한다금액은 큰 수보다 정확한 수라는 조건이 먼저다이름의 글자 수와 저장 바이트, 같은 이름의 기준은 다르다날짜와 사건이 일어난 순간을 구분한다작은 열 선택이 큰 데이터 오류로 이어지는 경우3. 행은 저장 페이지에 함께 실린다계산 예: 100바이트 행은 8KiB 페이지에 81개씩 들어갈까같은 행 수를 더 여유 있게 배치하면적은 행을 반환해도 많은 페이지를 읽을 수 있다이 부분의 출처와 가정4. 원하는 행까지의 경로를 사용 방식에 맞춘다나무 그림은 값을 보관하는 위치와 안내하는 위치를 나누어 읽는다고객을 먼저 모은 뒤 그 안에서 최신 주문을 찾는다드물게 나오는 값과 자주 나오는 값은 같은 인덱스에서도 다르다전체 열에 보통 인덱스를 하나씩 만드는 것 외에도 선택이 있다묶어 저장하는 방식은 제품 이름과 읽는 방향을 구분한다문구점의 인덱스 후보를 채택·보류 이유로 기록한다5. 큰 표를 나눌 때는 어떤 질문에서 건너뛸 수 있는지 본다9월 데이터만 묻는다면 8월과 10월을 제외할 수 있다나누는 기준 때문에 원래의 유일성이 약해질 수 있다파티션의 이득이 작으면 나누지 않는 것도 설계다6. 중복을 둘 때는 무엇이 원본인지 먼저 적는다7. 용량은 테이블 파일 하나의 크기로 끝나지 않는다계산 예: 본체 134MiB인 표에 134MiB 디스크만 주면 부족하다저장 위치와 큰 값의 처리도 운영 결정이다8. 예상한 경로와 실제 비용을 같은 조건에서 대조한다평균 읽기만 개선된 후보를 최종안으로 뽑지 않는다좋은 인덱스도 변경 중에는 서비스에 비용을 줄 수 있다설계 실패를 징후와 수정 책임으로 연결한다요구에서 승인 가능한 검증 자료까지 이어지는 순서물리 설계의 답안은 하나의 인덱스보다 넓다9. 기출의 개별 논점을 통합 선택으로 바꾼다10. 10점 전환: 질의에서 인덱스 선택으로답안 목차답안 도식10점 모범답안11. 25점 전환: 의미를 지키며 읽기·쓰기·공간을 함께 설계한다답안 목차답안 도식25점 모범답안제품별 근거와 자체 사례의 경계다시 읽을 때 붙잡을 한 줄