함수종속과 식별/비식별

서버란·2024년 10월 14일

CS 지식

목록 보기
22/25

데이터베이스에서 함수 종속, 외래키 연결, 식별/비식별 관계에 대한 개념은 데이터베이스 설계와 관계형 데이터 모델에서 매우 중요한 주제들입니다. 각각에 대해 차례로 설명해 드리겠습니다.

1. 함수 종속 (Functional Dependency)

함수 종속(Functional Dependency)은 데이터베이스에서 속성 간의 관계를 나타냅니다. 이는 어떤 속성(A)이 다른 속성(B)에 대해 유일하게 값을 결정할 수 있을 때를 말합니다. 일반적으로 함수 종속을 다음과 같이 표기합니다:

A → B

여기서, A는 결정자(determinant), B는 종속자(dependent)입니다. 즉, A가 B를 결정한다는 의미로, A 값이 같으면 B 값도 항상 동일해야 한다는 규칙을 따릅니다.

예시
학생 데이터베이스에서 학번이 학생의 이름을 결정할 수 있습니다.

학번 → 이름

이 의미는 특정 학번에 대해 하나의 이름만 있을 수 있다는 것입니다. 따라서 학번이 동일하면 이름도 동일해야 합니다.

함수 종속의 종류

  • 완전 함수 종속: 키 전체에 의해서만 결정되는 종속성입니다. 예를 들어, 복합키 (A, B)가 있을 때 B가 전체 키 (A, B)에 완전히 종속된다면, A만으로는 B가 결정될 수 없습니다.
  • 부분 함수 종속: 복합키의 일부에 의해 종속되는 경우입니다. 예를 들어 (A, B)가 기본 키일 때, B가 A에 의해 결정되면 이는 부분 함수 종속입니다.
  • 이행적 함수 종속: A → B, B → C가 성립하면 A → C가 성립하는 관계입니다.

2. 외래키 (Foreign Key)와 관계

외래키(Foreign Key)는 한 테이블의 필드가 다른 테이블의 기본 키(Primary Key)를 참조할 때 사용됩니다. 외래키는 테이블 간의 관계를 정의하며, 두 테이블 간의 참조 무결성(Referential Integrity)을 유지하는 데 중요합니다.

예시
학생과 수강 테이블이 있다고 가정해봅시다. 학생 테이블에는 학생번호가 기본 키이고, 수강 테이블에는 수강번호와 함께 학생번호가 있습니다. 여기서 수강 테이블의 학생번호는 학생 테이블의 학생번호를 참조하는 외래키입니다.

학생(학생번호, 이름)
수강(수강번호, 학생번호, 과목)

여기서 수강 테이블의 학생번호는 외래키로서 학생 테이블의 학생번호를 참조합니다.

3. 식별 관계 vs 비식별 관계

테이블 간의 관계에서 식별(Identifying) 관계와 비식별(Non-Identifying) 관계는 외래키를 사용할 때 어떤 방식으로 관계를 설정하느냐에 따라 구분됩니다.

3.1. 식별 관계 (Identifying Relationship)

식별 관계는 자식 테이블의 외래키가 부모 테이블의 기본 키의 일부가 되는 관계를 말합니다. 즉, 자식 테이블의 기본 키는 부모 테이블의 기본 키에 의존하게 됩니다. 이때, 자식 테이블은 부모 테이블 없이 존재할 수 없습니다.

  • 부모 테이블의 기본 키가 자식 테이블의 기본 키에 포함됨
  • 부모의 존재 없이 자식 테이블 레코드는 의미가 없음
  • 주로 강한 종속성이 있을 때 사용

예시
가령 Order(주문)와 OrderItem(주문 항목) 테이블이 있을 때, 주문 항목은 주문과 반드시 연결되어야 하므로 OrderItem의 기본 키는 Order의 기본 키를 포함하게 됩니다.

CREATE TABLE Order (
    order_id INT PRIMARY KEY
);

CREATE TABLE OrderItem (
    order_id INT,
    item_id INT,
    PRIMARY KEY (order_id, item_id),
    FOREIGN KEY (order_id) REFERENCES Order(order_id)
);

여기서 OrderItem의 기본 키는 (order_id, item_id)이고, order_id는 부모 테이블의 기본 키와 연결되어 있습니다. 이것이 식별 관계입니다.

3.2. 비식별 관계 (Non-Identifying Relationship)

비식별 관계는 자식 테이블의 외래키가 부모 테이블의 기본 키와는 별개로 자식 테이블의 고유한 기본 키를 가질 때 사용됩니다. 부모와 자식이 독립적인 기본 키를 가질 수 있으며, 부모 테이블의 존재 여부와 상관없이 자식 테이블의 레코드는 독립적으로 존재할 수 있습니다.

  • 자식 테이블이 부모 테이블의 외래키를 가짐
  • 자식 테이블의 기본 키는 독립적임
  • 부모와 자식 간 약한 종속성

예시
Student와 Course 테이블이 있고, Enrollment(수강 신청) 테이블이 있다고 가정해봅시다. Enrollment는 학생과 강좌 간의 관계를 나타내지만, 학생과 강좌는 각각 독립적인 테이블입니다. 이 경우 Enrollment는 비식별 관계가 됩니다.

CREATE TABLE Student (
    student_id INT PRIMARY KEY,
    name VARCHAR(50)
);

CREATE TABLE Course (
    course_id INT PRIMARY KEY,
    title VARCHAR(100)
);

CREATE TABLE Enrollment (
    enrollment_id INT PRIMARY KEY,
    student_id INT,
    course_id INT,
    FOREIGN KEY (student_id) REFERENCES Student(student_id),
    FOREIGN KEY (course_id) REFERENCES Course(course_id)
);

여기서 Enrollment 테이블은 자체적으로 enrollment_id라는 기본 키를 가지며, 부모 테이블 Student와 Course의 외래키를 참조합니다. 이 관계는 부모 테이블의 기본 키가 자식 테이블의 기본 키에 포함되지 않기 때문에 비식별 관계라고 합니다.

정리

  • 함수 종속: 한 속성이 다른 속성에 종속적인 관계. 예: 학번 → 이름.
  • 외래키: 한 테이블이 다른 테이블의 기본 키를 참조하는 키. 테이블 간의 관계를 표현.
  • 식별 관계: 자식 테이블의 기본 키가 부모 테이블의 기본 키를 포함하는 강한 종속성.
  • 비식별 관계: 자식 테이블의 기본 키가 독립적이며 부모 테이블의 기본 키와 직접적인 연관이 없는 약한 종속성.

Q1: 식별 관계와 비식별 관계 중 어느 상황에서 더 적합한지 판단하는 기준은 무엇인가요?

식별 관계와 비식별 관계는 데이터의 의존성에 따라 적절하게 선택됩니다. 주로 데이터 간의 강한 종속성이 필요한 경우에는 식별 관계를, 상대적으로 독립적인 데이터 관계를 표현할 때는 비식별 관계를 사용합니다.

  1. 식별 관계를 사용하는 경우:
  • 강한 의존성: 자식 테이블이 부모 테이블 없이는 존재할 수 없는 경우입니다. 예를 들어, 주문(Order)주문 항목(OrderItem)의 관계에서, 주문 항목은 반드시 주문과 연결되어야만 의미가 있습니다. 주문 항목이 주문 없이 존재할 수 없다면, 식별 관계를 사용하여 자식 테이블의 기본 키에 부모 테이블의 키를 포함시킵니다.

  • 복합 키가 자연스러운 경우: 자식 테이블에서 부모 테이블의 기본 키가 자식 테이블의 기본 키에 포함되어야 하는 경우, 식별 관계를 사용하는 것이 적합합니다.

  1. 비식별 관계를 사용하는 경우:
  • 약한 의존성: 자식 테이블이 부모 테이블과 독립적으로 존재할 수 있는 경우입니다. 예를 들어, 수강 신청(Enrollment) 테이블에서 학생과 강좌가 각각 독립적인 엔터티로 존재할 수 있으며, 수강 신청 레코드는 독립적인 기본 키를 가질 수 있습니다. 이 경우 비식별 관계가 적합합니다.
  • 외래키가 기본 키가 아니어야 하는 경우: 자식 테이블이 부모 테이블의 키에 의존적일 필요는 없고, 자신의 고유한 기본 키를 가져야 하는 경우에는 비식별 관계가 적합합니다.

따라서 데이터 간의 의존성이 매우 강하면 식별 관계를, 데이터가 독립적이거나 별도의 기본 키가 필요할 경우 비식별 관계를 사용합니다.

Q2: 함수 종속성을 기반으로 테이블을 설계할 때, 정규화를 어떻게 적용할 수 있을까요?

함수 종속성을 기반으로 테이블을 설계할 때는 정규화 과정을 통해 데이터 중복을 최소화하고, 데이터의 일관성을 유지할 수 있습니다. 정규화 과정은 여러 단계로 나뉘며, 각 단계에서 함수 종속성을 해결하는 방법이 달라집니다.

  1. 제1정규형 (1NF):
  • 테이블이 1NF를 만족하려면, 모든 속성의 값이 원자적(atomic)이어야 합니다. 즉, 각 속성은 더 이상 분해되지 않는 단일 값만을 가져야 합니다.
  • 예시: 만약 한 테이블의 전화번호 필드에 여러 개의 전화번호가 들어가 있다면, 이를 각각의 행으로 나누어야 1NF를 만족합니다.
  1. 제2정규형 (2NF):
  • 2NF는 1NF를 만족하면서 부분 함수 종속성을 제거해야 합니다. 복합 키가 사용될 때, 한 속성이 복합 키의 일부분에만 종속된다면 이를 분리해야 합니다.
  • 예시: 만약 학생ID, 수업ID가 복합 키로 설정된 수강 테이블에서 학생이름이 학생ID에만 종속된다면, 이를 별도의 학생 테이블로 분리하여 처리해야 합니다.
  1. 제3정규형 (3NF):
  • 2NF를 만족하면서 이행적 함수 종속성을 제거합니다. 즉, A → B, B → C의 관계가 있을 때 A → C를 유도하는 경우, 이를 분리해야 합니다.
  • 예시: 만약 학생 테이블에서 학과ID가 학과명을 결정할 수 있다면, 이를 별도의 학과 테이블로 분리하는 것이 좋습니다.

정규화 과정에서는 주로 함수 종속성을 분석하고, 각 테이블에 중복 데이터가 없는지, 불필요한 종속성이 없는지를 확인합니다. 정규화가 지나치면 성능이 저하될 수 있으므로, 정규화와 성능 사이의 균형을 맞추는 것이 중요합니다.

Q3: 외래키를 설정할 때 발생할 수 있는 성능 문제를 해결하는 방법은 무엇인가요?

외래키는 데이터베이스에서 테이블 간의 관계를 설정하는 데 매우 중요하지만, 성능에 영향을 줄 수 있는 몇 가지 문제가 발생할 수 있습니다. 이를 해결하기 위한 몇 가지 방법은 다음과 같습니다.

  1. 인덱스 생성:
  • 외래키가 참조하는 컬럼에 인덱스를 생성하면 성능을 크게 향상시킬 수 있습니다. 외래키는 주로 다른 테이블의 기본 키를 참조하므로, 참조되는 컬럼에 인덱스를 걸어두면 조회 및 삭제 시 속도가 빨라집니다.
  • 예시: student_id와 course_id에 인덱스를 걸어두면 Enrollment 테이블에서 학생과 강좌를 빠르게 조회할 수 있습니다.
  1. 적절한 캐싱 사용:
  • 자주 참조되는 외래키 관계는 캐시를 사용하여 성능을 최적화할 수 있습니다. 예를 들어, 자주 사용되는 참조 데이터를 애플리케이션 레벨에서 캐싱함으로써 데이터베이스에 직접적인 접근을 줄일 수 있습니다.
  • 예시: 수강 신청 과정에서 자주 조회되는 강좌 정보를 메모리나 애플리케이션 캐시에서 처리하여 데이터베이스 부하를 줄일 수 있습니다.
  1. 연쇄 작업을 주의 깊게 관리:
  • 외래키 제약 조건을 설정할 때 ON DELETE CASCADE나 ON UPDATE CASCADE와 같은 연쇄 작업은 편리하지만, 성능에 영향을 미칠 수 있습니다. 특히, 참조 테이블의 데이터가 많을 경우 이러한 연쇄 작업이 시간이 오래 걸릴 수 있습니다.
  • 연쇄 작업은 필요한 경우에만 사용하고, 가능한 한 성능에 미치는 영향을 줄이는 방향으로 설정하는 것이 좋습니다.
  1. 배치 작업 활용:
  • 많은 데이터를 한 번에 삽입하거나 업데이트할 때는 배치 처리(batch processing)를 통해 성능을 최적화할 수 있습니다. 외래키가 있는 테이블에서 대량의 데이터를 한꺼번에 처리하면 성능이 저하될 수 있으므로, 배치 작업을 통해 효율적으로 처리하는 것이 좋습니다.

정리하면, 인덱스 생성, 캐싱, 연쇄 작업 관리, 배치 처리 등의 방법을 통해 외래키로 인해 발생할 수 있는 성능 문제를 해결할 수 있습니다.

profile
백엔드에서 서버엔지니어가 된 사람

0개의 댓글