[DB/SQL] 테이블 설계 (정규화, 인덱스, 제약조건)

songeunm·2025년 5월 19일

DB & SQL

목록 보기
14/27

🎱 정규화(Normalization)

테이블을 중복 없이 논리적으로 잘게 나누는 과정

⚾️ 정규화의 목적

  • 데이터 무결성 보장 → 여러 테이블의 데이터가 변경시 자동 업데이트
  • 데이터 중복 제거 → 유지보수 용이
  • 저장 공간 절약 → 중복 데이터가 감소하면서 효율적 저장
  • 관계 명확화 → 테이블 간의 관계가 분리되어 설계 명확화

⚾️ 정규형

  • 1NF (제1정규형)
    • 모든 컬럼이 원자값만 가짐
    • 즉, 리스트 형태 등이 값으로 들어오지 않음
    • ex) 한 명이 여러 과목을 수강할 시 레코드로 분리 필요
      StudentIDCourse
      123컴퓨터구조, 자료구조, 이산수학
  • 2NF (제2정규형)
    • 부분 종속 제거
    • 복합 PK 사용 시 PK 일부에만 의존하는 컬럼 제거
    • ex) 학생 이름은 학번에만 의존하므로 테이블 분리 필요
      StudentIDCourseIDName
      123456Peter Parker
  • 3NF (제3정규형)
    • 이행적 종속 제거
    • A → B → C 관계일 때, C는 A에 직접 종속되어야 함
    • ex) 과목명은 과목ID에 종속되므로 별도의 테이블로 분리 필요
      StudentIDCourseIDCourse
      123456컴퓨터구조

⚾️ 반정규화

쿼리 성능이나 데이터 접근 편의성을 위해 일부 정규화를 깨는 것

🎱 인덱스(Index)

검색 속도를 빠르게 하기 위해 특정 컬럼에 색인 구조를 만드는 것

CREATE INDEX idx_StudentID ON Students(StudentID);

⚾️ 원리

대부분의 RDBMS 인덱스는 B-Tree 구조 사용
➡️ 정렬된 트리 형태로 데이터를 저장해 빠르게 이진 탐색 가능

⚾️ 인덱스 남용

모든 컬럼에 인덱스를 걸면 좋을 것 같지만 다음과 같은 문제점들이 발생

  • INSERT/UPDATE 성능 저하 인덱스도 같이 갱신되기 때문에 부하 발생
  • 저장 공간 증가 인덱스는 별도로 디스크에 저장됨. 컬럼당 수 MB~수 GB까지 쌓일 수 있음
  • 옵티마이저 혼란 인덱스가 너무 많으면 옵티마이저가 “어떤 인덱스를 써야 할지” 판단하는 데 비용이 더 듦

➡️ 실무에선 “조회 조건으로 자주 쓰는 컬럼만” 인덱스 설정

⚾️ 커버링 인덱스?

  • 쿼리에 필요한 컬럼들이 전부 인덱스에 포함된 상태
    ⇒ 인덱스만 보고도 결과를 반환할 수 있는 경우
  • 커버링 인덱스 X
    -- user_id에는 인덱스가 있음
    SELECT name FROM users WHERE user_id = 'abc123';
  • 커버링 인덱스
    -- 복합 인덱스: (user_id, name)
    SELECT name FROM users WHERE user_id = 'abc123';

🎱 제약조건(Constraints)

데이터의 무결성을 보장하기 위해 테이블 수준에서 제한을 거는 규칙

⚾️ 제약 종류

  • PRIMARY KEY 중복 불가능, 값이 NULL일 수 없음
  • NOT NULL 값이 NULL일 수 없음
  • UNIQUE 중복 불가능
  • CHECK 값의 범위 제한
    MySQL 8.0 이상에서 사용 가능
  • FOREIGN KEY 다른 테이블과 참조 연결

⚾️ 제약 추가 및 삭제

-- 제약 추가
ALTER TABLE Students ADD CONSTRAINT grade_range CHECK (Grade BETWEEN 1 AND 4);

-- 제약 삭제
ALTER TABLE Students DROP CHECK grade_range;
CREATE TABLE Students 
profile
데굴데굴 구르는 개발자 지망생

0개의 댓글