Chapter 2. Introduction to the Relational Model
한 줄 핵심: 관계형 모델은 데이터를 테이블(릴레이션)의 집합으로 표현하고, 키로 튜플을 식별·연결하며, 관계 대수라는 절차적 언어로 릴레이션을 입력받아 새 릴레이션을 만들어 질의한다.
이 챕터가 답하는 핵심 질문
- Q1. 관계형 모델은 데이터를 어떻게 구조화하는가?
- Q2. 속성 값에는 어떤 제약이 있는가? (도메인·원자성·null)
- Q3. 스키마와 인스턴스, 그리고 튜플의 순서는?
- Q4. 튜플을 식별하고 릴레이션을 연결하는 키에는 어떤 종류가 있는가?
- Q5. 스키마 다이어그램은 무엇을 보여주는가?
- Q6. 관계 대수란 무엇이고 왜 “절차적” 언어인가?
- Q7. 6개 기본 연산자는 각각 무엇을 하는가?
- Q8. 기본 연산 외에 자주 쓰는 추가 연산은? (∩, ⋈, ←)
- Q9. 같은 결과를 내는 쿼리가 여러 개일 수 있는가? (동치 쿼리)
Q1. 관계형 모델은 데이터를 어떻게 구조화하는가?
A. 데이터를 릴레이션(relation), 즉 테이블의 집합으로 표현한다.
기본 용어:
- 릴레이션(Relation): 테이블. 행과 열로 구성.
- 튜플(Tuple): 릴레이션의 한 행(row). 하나의 레코드.
- 속성(Attribute): 릴레이션의 한 열(column). 각 속성은 이름을 가짐.
- 릴레이션 스키마(Relation Schema): 릴레이션의 논리적 설계.
R = (A₁, A₂, ..., Aₙ)형태.- 예:
instructor = (ID, name, dept_name, salary)
- 예:
- 릴레이션 인스턴스(Relation Instance): 스키마 R 위에 정의된 실제 데이터
r(R). 현재 값들이 테이블로 표현되며, 그 원소 t(튜플)가 한 행.
Q2. 속성 값에는 어떤 제약이 있는가? (도메인·원자성·null)
A. 각 속성은 허용 값의 집합인 도메인을 가지며, 값은 보통 **원자적(atomic)**이어야 하고, 특수 값 null이 존재한다.
- 도메인(Domain): 각 속성에 허용되는 값의 집합.
- 원자적(Atomic): 값은 더 이상 분할할 수 없어야 한다.
- 예: 전화번호를 하나의 값으로 두면 원자적. 국가코드/지역코드/번호로 쪼개 부분 값으로 쓰면 위반.
- null: “값을 모름(unknown)“을 나타내는 특수 값. 모든 도메인의 멤버다. 많은 연산의 정의를 복잡하게 만든다.
Q3. 스키마와 인스턴스, 그리고 튜플의 순서는?
A. 스키마는 논리적 구조(타입), **인스턴스는 특정 시점의 데이터 스냅샷(값)**이며, 튜플의 순서는 무의미하다.
- 데이터베이스 스키마(Database Schema): 데이터베이스의 논리적 구조. (예:
instructor(ID, name, dept_name, salary)) - 데이터베이스 인스턴스(Database Instance): 특정 시점의 데이터 스냅샷(snapshot).
- 비유: 스키마 = 변수의 타입, 인스턴스 = 변수의 값.
- 튜플의 순서는 무의미하다 (Relations are Unordered): 릴레이션은 튜플의 집합이므로 저장 순서는 임의적이며, 어떤 순서로 나열해도 같은 릴레이션이다.
Q4. 튜플을 식별하고 릴레이션을 연결하는 키에는 어떤 종류가 있는가?
A. 슈퍼키 ⊃ 후보키 ⊃ 기본키의 포함 관계로 튜플을 식별하고, 외래키로 다른 릴레이션을 참조한다.
K ⊆ R 일 때:
| 키 유형 | 정의 |
|---|---|
| 슈퍼키 (Superkey) | K 값으로 각 튜플을 유일하게 식별할 수 있으면 슈퍼키. {ID}도, {ID, name}도 슈퍼키. |
| 후보키 (Candidate Key) | 최소(minimal) 슈퍼키. 어떤 진부분집합도 슈퍼키가 아닌 슈퍼키. 예: {ID}. |
| 기본키 (Primary Key) | 후보키 중 DBA가 선택한 대표 키. 밑줄로 표시. 묶인 여러 밑줄은 함께 하나의 복합 기본키. |
| 외래키 (Foreign Key) | 한 릴레이션의 값이 다른 릴레이션에 반드시 나타나야 하는 제약. 릴레이션 간 관계를 표현. |
키 종류를 실제 데이터로 구분하기
instructor(ID, name, dept_name, salary)테이블에서:
ID name dept_name salary 22222 Einstein Physics 95000 12121 Wu Finance 90000 33456 Gold Physics 87000
- 슈퍼키: 행을 유일하게 구분만 하면 OK.
{ID}✅,{ID, name}✅ (군더더기 name이 붙어도 여전히 유일하니 슈퍼키),{name}✅ (지금은 이름이 안 겹치지만 동명이인이 생기면 깨지므로 보통 키로 안 씀).- 후보키: 슈퍼키 중 “한 글자도 못 빼는” 최소 조합.
{ID}는 ID 하나만으로 유일 → 후보키.{ID, name}은 name을 빼도 유일하므로 최소가 아님 → 후보키 아님.- 기본키: 후보키
{ID}를 DBA가 대표로 지정 → ID처럼 밑줄.직관: 슈퍼키는 “넉넉하게 구분되면 됨”, 후보키는 “더 못 줄일 만큼 딱 맞게”, 기본키는 “그중 공식 대표 하나”.
외래키 제약(Foreign Key Constraint): 참조하는 릴레이션(referencing relation)의 값이 참조되는 릴레이션(referenced relation)에 반드시 존재해야 한다.
- 예: instructor의
dept_name은 department를 참조하는 외래키.instructor(ID, name, dept_name, salary)— dept_name = 외래키department(dept_name, building, budget)— dept_name = 기본키
외래키는 "유령 참조"를 막는다
department(dept_name 기본키) instructor(dept_name 외래키) ┌───────────┐ ┌───────┬──────────┬───────────┐ │ Physics │ <───── 참조 ────────│ 22222 │ Einstein │ Physics │ ✅ │ Finance │ <───── 참조 ────────│ 12121 │ Wu │ Finance │ ✅ └───────────┘ │ 99999 │ Lee │ Magic │ ❌ └───────┴──────────┴───────────┘“Magic”은 department에 없는 학과 → 외래키 제약이 이 행의 삽입을 거부한다. 덕분에 “존재하지 않는 학과 소속 교수” 같은 모순 데이터가 들어올 수 없다.
한 줄 정리
연결 고리가 되는 컬럼은 양쪽 테이블에 다 있어야 관계를 맺을 수 있지만, 외래키라는 제약조건은 참조하는(자식) 테이블에만 정의한다.
Q5. 스키마 다이어그램은 무엇을 보여주는가?
A. 데이터베이스의 논리적 구조를 시각화한다 — 각 릴레이션은 직사각형, 기본키는 밑줄, 외래키 관계는 화살표(참조 → 피참조).
대학 스키마의 주요 릴레이션:
department(dept_name, building, budget)
course(course_id, title, dept_name, credits)
instructor(ID, name, dept_name, salary)
section(course_id, sec_id, semester, year, building, room_number, time_slot_id)
teaches(ID, course_id, sec_id, semester, year)
student(ID, name, dept_name, tot_cred)
takes(ID, course_id, sec_id, semester, year, grade)
advisor(s_ID, i_ID)
prereq(course_id, prereq_id)
classroom(building, room_number, capacity)
time_slot(time_slot_id, day, start_hr, start_min, end_hr, end_min)
course 릴레이션 (샘플):
| course_id | title | dept_name | credits |
|---|---|---|---|
| BIO-101 | Intro. to Biology | Biology | 4 |
| CS-101 | Intro. to Computer Science | Comp. Sci. | 4 |
| CS-347 | Database System Concepts | Comp. Sci. | 3 |
| PHY-101 | Physical Principles | Physics | 4 |
prereq 릴레이션 (선수과목, 샘플):
| course_id | prereq_id |
|---|---|
| BIO-301 | BIO-101 |
| CS-347 | CS-101 |
| EE-181 | PHY-101 |
Q6. 관계 대수란 무엇이고 왜 “절차적” 언어인가?
A. 관계 대수는 하나 또는 두 개의 릴레이션을 입력받아 새 릴레이션을 산출하는 연산들의 집합이며, “어떻게(How)” 연산을 순서대로 적용할지 지정하므로 절차적(procedural) 언어다.
6개 기본 연산자: select(σ), project(Π), union(∪), set difference(−), Cartesian product(×), rename(ρ).
절차적(Procedural) vs 선언적(Declarative)
- 절차적(How): 결과를 얻기 위한 연산의 순서·절차를 지정. 관계 대수가 여기 속한다.
- 예: “먼저 σ로 나이 ≥ 20인 행을 고르고, 그 결과에 Π로 이름만 추출하라.”
- 선언적/비절차적(What): 원하는 결과의 **성질(조건)**만 정의, 방법은 시스템에 위임.
- 관계 해석(Relational Calculus): 관계 대수의 짝. 무엇을 원하는지만 선언.
- SQL: 대표적 선언적 언어. 인덱스를 쓸지 풀 스캔할지는 DBMS의 Optimizer가 결정.
핵심 성질 — 연산의 합성(Composition)
관계 대수 연산의 결과는 항상 릴레이션이므로 연산을 중첩(합성)할 수 있다.
예:Π_name(σ_{dept_name="Physics"}(instructor))— 선택 결과(릴레이션)에 투영을 바로 적용.
Q7. 6개 기본 연산자는 각각 무엇을 하는가?
A. 행을 거르고(σ), 열을 뽑고(Π), 집합 연산(∪, −)을 하고, 두 릴레이션을 조합(×)하고, 이름을 바꾼다(ρ).
아래 예제에서 공통으로 쓸 샘플 데이터
instructor
ID name dept_name salary 10101 Srinivasan Comp. Sci. 65000 22222 Einstein Physics 95000 33456 Gold Physics 87000 12121 Wu Finance 90000 직관 한 줄: σ는 “가로줄(행)을 자르는 가위”, Π는 “세로줄(열)을 자르는 가위”라고 외우면 헷갈리지 않는다.
Π (열을 뽑음, 세로 ↓) │ ─────┼──────────────── σ (행을 거름, 가로 →) │
Select — σ (행 선택)
조건(predicate)을 만족하는 **튜플(행)**만 선택.
σ_{조건}(릴레이션)
σ_{dept_name="Physics" ∧ salary>90000}(instructor)
- 비교:
=, ≠, >, ≥, <, ≤/ 논리:∧(and), ∨(or), ¬(not) - 두 속성 간 비교도 가능:
σ_{dept_name=building}(department)
σ 단계별 추적 —
σ_{dept_name="Physics"}(instructor)위 instructor의 4개 행을 한 줄씩 조건 검사:
10101 Srinivasan Comp.Sci. 65000 → Physics 아님 ✗ 버림 22222 Einstein Physics 95000 → Physics 맞음 ✓ 남김 33456 Gold Physics 87000 → Physics 맞음 ✓ 남김 12121 Wu Finance 90000 → Physics 아님 ✗ 버림결과 (열 구조는 그대로, 행만 줄어듦):
ID name dept_name salary 22222 Einstein Physics 95000 33456 Gold Physics 87000
Project — Π (열 추출)
지정한 **속성(열)**만 남기고 나머지 열을 지운다. 결과의 중복 튜플은 자동 제거(릴레이션은 집합이므로).
Π_{ID, name, salary}(instructor)
Π가 중복을 제거하는 모습 —
Π_{dept_name}(instructor)dept_name 열만 뽑으면 Physics가 두 번 나오지만, 릴레이션은 집합이라 자동으로 1개만 남는다.
뽑힌 값: Comp. Sci. / Physics / Physics / Finance └── 중복! 하나로 합쳐짐결과:
dept_name Comp. Sci. Physics Finance
σ와 Π의 합성 —
Π_name(σ_{dept_name="Physics"}(instructor))안쪽 σ로 Physics 행 2개를 고른 뒤, 그 결과(릴레이션)에 Π로 name만 뽑는다.
instructor ──σ_{Physics}──> [22222 Einstein …][33456 Gold …] ──Π_name──> ┌──────────┐ │ Einstein │ │ Gold │ └──────────┘핵심: σ의 결과가 다시 릴레이션이므로 Π를 곧바로 적용할 수 있다 (연산의 합성).
Union — ∪ (합집합)
두 릴레이션의 모든 튜플 합침. 중복 제거.
r ∪ s
- 호환 조건: ① 같은 수의 속성(same arity), ② 대응 속성의 도메인 호환.
-- 2017 Fall 또는 2018 Spring에 개설된 과목
Π_{course_id}(σ_{semester="Fall" ∧ year=2017}(section))
∪ Π_{course_id}(σ_{semester="Spring" ∧ year=2018}(section))
∪ / − / ∩ 를 같은 데이터로 한눈에 비교
두 학기에 개설된 과목 집합이 아래와 같다고 하자.
Fall2017 = { CS-101, CS-347, PHY-101 } Spring2018 = { CS-101, CS-315, FIN-201 } └ 양쪽에 다 있는 건 CS-101 뿐
연산 의미 결과 ∪ (합집합) 둘 중 하나라도 개설 CS-101, CS-347, PHY-101, CS-315, FIN-201 ∩ (교집합) 양쪽 모두 개설 CS-101 − (차집합) Fall−Spring Fall엔 있고 Spring엔 없는 CS-347, PHY-101 직관: ∪=“둘을 합쳐 중복 제거”, ∩=“겹치는 부분만”, −=“내 것에서 상대 것을 뺀 나머지”. 벤다이어그램 그대로다.
Set Difference — − (차집합)
r에는 있지만 s에는 없는 튜플. 호환 조건은 union과 동일.
-- 2017 Fall에는 있고 2018 Spring에는 없는 과목
Π_{course_id}(σ_{...Fall,2017}(section)) − Π_{course_id}(σ_{...Spring,2018}(section))
Cartesian Product — × (카티션 곱)
두 릴레이션의 모든 튜플 쌍을 조합. 결과 속성은 양쪽 속성을 모두 포함하며, 공통 속성은 릴레이션 이름으로 구분(instructor.ID, teaches.ID).
instructor × teaches
왜 곱 결과 대부분이 무의미한가: instructor 5개 × teaches 13개 = 65개 튜플. 이 중 instructor.ID = teaches.ID를 만족하는 의미 있는 조합은 일부뿐. 나머지는 무관한 교수-강의 쌍. 따라서 거의 항상 σ 조건과 함께 쓴다.
× 를 작은 데이터로 직접 추적
instructor (2개) × teaches (2개) = 4개(2×2)의 모든 짝.
instructor teaches ┌───────┬──────────┐ ┌───────┬──────────┐ │ 22222 │ Einstein │ │ 22222 │ PHY-101 │ │ 12121 │ Wu │ │ 12121 │ FIN-201 │ └───────┴──────────┘ └───────┴──────────┘모든 쌍을 만들면:
instructor.ID name teaches.ID course_id 의미? 22222 Einstein 22222 PHY-101 ✅ Einstein이 자기 과목 22222 Einstein 12121 FIN-201 ❌ Einstein인데 Wu의 과목 12121 Wu 22222 PHY-101 ❌ Wu인데 Einstein의 과목 12121 Wu 12121 FIN-201 ✅ Wu가 자기 과목 직관: 곱은 “양쪽을 무지성으로 다 짝지은” 상태라 절반이 엉뚱하다. 그래서
instructor.ID = teaches.ID로 대각선(✅)만 남기는 게 핵심.
σ_{instructor.ID = teaches.ID}(instructor × teaches)
위 4개 중 ID가 같은 2개(✅)만 남는다 → 이것이 바로 다음 절의 조인이다.
Rename — ρ (재명명)
연산 결과 릴레이션에는 이름이 없으므로, 이름(또는 속성 이름)을 부여한다. SQL의 AS에 대응.
ρ_x(E) — 결과 E를 x로 명명
ρ_{x(A₁,A₂,...,Aₙ)}(E) — 릴레이션 이름 x, 속성 이름도 모두 변경
Q8. 기본 연산 외에 자주 쓰는 추가 연산은? (∩, ⋈, ←)
A. 교집합(∩), 조인(⋈), 배정(←)은 편의를 위한 추가 연산이며, 기본 연산자로 표현 가능하다.
Set Intersection — ∩ (교집합)
r과 s 양쪽 모두에 있는 튜플. 호환 조건 동일.
r ∩ s = r − (r − s)
-- 2017 Fall과 2018 Spring 모두에 개설된 과목
Π_{course_id}(σ_{...Fall,2017}(section)) ∩ Π_{course_id}(σ_{...Spring,2018}(section))
Join — ⋈ (조인)
조인은 select + Cartesian product를 하나로 합친 연산이다. 카티션 곱에서 대부분 무의미한 행을 σ로 걸러내는 흔한 패턴을 한 연산으로 표현한다.
- Theta Join: 조건 θ를 직접 명시.
- 릴레이션 r(R), s(S)에 대해 θ는 스키마 R ∪ S 위의 술어(predicate).
- 정의:
- 예:
σ_{instructor.ID = teaches.ID}(instructor × teaches)=instructor ⋈_{instructor.ID = teaches.ID} teaches
조인 = "곱 만들고 → 골라내기"를 한 번에
앞 Q7의 × 예제 결과(4행)에서 ID가 일치하는 행만 남기면 조인 결과가 된다.
instructor ⋈_{instructor.ID = teaches.ID} teaches ① 곱: 모든 짝 4개 생성 ──> ② σ: ID 같은 행만 남김결과:
ID name course_id 22222 Einstein PHY-101 12121 Wu FIN-201 직관: 조인은 “두 표를 공통 열(ID)을 기준으로 자석처럼 딱 붙이는” 연산. 엑셀의 VLOOKUP, 인맥으로 치면 “이름이 같은 사람끼리 연결”하는 것과 같다. 실무 쿼리의 대부분이 조인이다.
Assignment — ← (배정)
중간 결과(릴레이션)에 임시 이름을 부여해 복잡한 쿼리를 순차 프로그램처럼 단계별로 작성. 프로그래밍의 대입과 같다.
Physics ← σ_{dept_name="Physics"}(instructor)
Music ← σ_{dept_name="Music"}(instructor)
Physics ∪ Music
Q9. 같은 결과를 내는 쿼리가 여러 개일 수 있는가? (동치 쿼리)
A. 그렇다. 관계 대수에서는 한 쿼리를 여러 방식으로 쓸 수 있으며, 결과가 같으면 **동치(equivalent)**다. Query Optimizer가 그중 가장 효율적인 것을 고른다.
동치 = “동일하지는 않지만(not identical), 어떤 데이터베이스에서도 같은 결과를 준다.”
예시 1 — Physics이고 salary > 90,000인 교수:
-- Query 1: 조건을 한 번에
σ_{dept_name="Physics" ∧ salary>90000}(instructor)
-- Query 2: 선택을 중첩
σ_{dept_name="Physics"}(σ_{salary>90000}(instructor))
예시 2 — Physics 학과 교수가 가르치는 과목 정보 (조인 순서/선택 위치의 차이):
-- Query 1: 조인 후 선택
σ_{dept_name="Physics"}(instructor ⋈_{instructor.ID=teaches.ID} teaches)
-- Query 2: 선택 후 조인 (보통 더 효율적 — 먼저 걸러 데이터를 줄임)
(σ_{dept_name="Physics"}(instructor)) ⋈_{instructor.ID=teaches.ID} teaches
두 쿼리는 같은 결과를 내지만 실행 비용이 다를 수 있다.
부록. 관계 대수 연산자 요약
| 연산자 | 기호 | 유형 | 설명 |
|---|---|---|---|
| Select | σ | 단항 | 조건을 만족하는 행 선택 |
| Project | Π | 단항 | 특정 열만 추출 (중복 제거) |
| Union | ∪ | 이항 | 합집합 |
| Set Difference | − | 이항 | 차집합 |
| Cartesian Product | × | 이항 | 모든 튜플 쌍 조합 |
| Rename | ρ | 단항 | 이름 변경 |
| Set Intersection | ∩ | 이항 | 교집합 (추가) |
| Join | ⋈ | 이항 | σ + × 결합 (추가) |
| Assignment | ← | — | 중간 결과 명명 (추가) |
출처: Database System Concepts, 7th Edition (Silberschatz, Korth, Sudarshan)