MySQL에서 “키(Key)”는 단순히 검색 속도를 높이기 위한 인덱스 개념을 넘는다.
데이터의 무결성을 보장하고, 테이블 간 관계를 정의하며, 중복을 방지하는 핵심 제약 조건이다.
PRIMARY KEY, UNIQUE KEY, FOREIGN KEY는 목적이 서로 다르다.
각 키의 역할을 명확히 구분하지 않으면 중복 데이터, 고아 레코드, 성능 저하 문제가 동시에 발생할 수 있다.
1. PRIMARY KEY
PRIMARY KEY는 테이블에서 각 행을 고유하게 식별하는 키다.
NULL을 허용하지 않으며, 테이블당 하나만 존재할 수 있다.
CREATE TABLE member (
id BIGINT UNSIGNED AUTO_INCREMENT,
email VARCHAR(255) NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
);
PRIMARY KEY는 자동으로 인덱스를 생성한다.
InnoDB에서는 클러스터드 인덱스로 동작하므로, PK 기준으로 데이터가 정렬 저장된다.
PK를 문자열로 설계하면 인덱스 크기가 커지고 성능이 저하될 수 있다.
실무에서는 BIGINT AUTO_INCREMENT 또는 Snowflake 계열 숫자 키를 사용하는 경우가 많다.
2. UNIQUE KEY
UNIQUE KEY는 특정 컬럼의 중복을 허용하지 않도록 제한하는 제약이다.
PRIMARY KEY와 달리 여러 개 설정할 수 있다.
ALTER TABLE member
ADD CONSTRAINT uk_member_email UNIQUE (email);
이메일처럼 중복되면 안 되는 값에 적용한다.
UNIQUE는 NULL을 하나 허용하는 점이 PRIMARY KEY와 다르다.
애플리케이션에서 “중복 체크 후 INSERT” 방식으로 처리하면 동시성 상황에서 레이스 컨디션이 발생한다.
DB 레벨에서 UNIQUE로 막는 것이 안전하다.
3. FOREIGN KEY
FOREIGN KEY는 테이블 간 참조 무결성을 보장한다.
자식 테이블의 값이 부모 테이블의 PRIMARY KEY 또는 UNIQUE KEY를 참조하도록 강제한다.
CREATE TABLE post (
id BIGINT UNSIGNED AUTO_INCREMENT,
member_id BIGINT UNSIGNED NOT NULL,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT fk_post_member
FOREIGN KEY (member_id)
REFERENCES member(id)
ON DELETE CASCADE
);
ON DELETE CASCADE를 설정하면 부모 데이터 삭제 시 자식 데이터도 함께 삭제된다.
옵션을 명시하지 않으면 RESTRICT로 동작하여 삭제가 차단된다.
FOREIGN KEY를 설정하지 않으면 고아 데이터가 발생할 수 있다.
특히 운영 중 직접 DELETE 쿼리를 실행할 경우 데이터 정합성이 쉽게 깨진다.
4. 키와 인덱스의 관계
PRIMARY KEY와 UNIQUE KEY는 자동으로 인덱스를 생성한다.
FOREIGN KEY 역시 참조 컬럼에 인덱스가 필요하다.
CREATE INDEX idx_post_member_id
ON post (member_id);
외래키 컬럼에 인덱스가 없으면 JOIN 성능이 급격히 저하된다.
대량 데이터 환경에서는 반드시 인덱스를 함께 고려해야 한다.
5. 자주 발생하는 문제
FOREIGN KEY가 생성되지 않는 경우
대부분은 스토리지 엔진이 MyISAM이기 때문이다.
FOREIGN KEY는 InnoDB에서만 지원된다.
SHOW TABLE STATUS WHERE Name = 'post';
Engine이 InnoDB인지 확인해야 한다.
컬럼 타입이 서로 다를 때도 FK 생성이 실패한다.
UNIQUE 충돌 오류
Duplicate entry 오류는 이미 동일 값이 존재한다는 의미다.
사전 중복 체크 대신 INSERT 시 예외를 잡는 구조가 동시성 환경에서 안전하다.
6. 설계 기준 정리
- 모든 테이블은 PRIMARY KEY를 가진다
- 중복되면 안 되는 값은 UNIQUE로 제한한다
- 테이블 간 관계는 FOREIGN KEY로 명시한다
- FK 컬럼에는 인덱스를 함께 설계한다
- 스토리지 엔진은 InnoDB를 사용한다
한 줄 요약
PRIMARY KEY는 행 식별, UNIQUE는 중복 방지, FOREIGN KEY는 참조 무결성 보장. 인덱스와 함께 설계하고 InnoDB 기준으로 관계를 명확히 정의하면 데이터 정합성과 성능을 동시에 확보할 수 있다.
댓글 0