VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
외래 키 정의하기
fk_orders_customer)은 선택 사항이지만 포함할 가치가 있습니다 — 오류 메시지에 나타나고 ALTER TABLE 작업을 쉽게 만듭니다.
외래 키에는 InnoDB가 필요합니다 — MyISAM은 조용히 무시합니다.
참조 동작
ON DELETE와 ON UPDATE 절은 참조된 부모 행이 삭제되거나 갱신될 때 자식 행에 무슨 일이 일어나는지 정의합니다.
SET DEFAULT는 SQL 표준의 일부입니다. InnoDB는 불평 없이 구문을 받아들이지만 구현하지는 않습니다 — 런타임에는 RESTRICT와 정확히 같게 동작합니다(ERROR 1451). 사용하지 마세요: 이름이 암시하는 것과 정반대로 조용히 동작합니다.
**DELETE 시 CASCADE**는 편리하지만 위험합니다. 고객을 삭제하면 그 고객의 모든 주문이 자동으로 삭제됩니다 — 오류도 경고도 없습니다. 종속 행이 부모 없이는 정말로 의미가 없을 때(예: 주문 없는 주문 품목)만 사용하세요.
**RESTRICT**가 더 안전한 기본값입니다 — 애플리케이션이 삭제를 명시적으로 처리하도록 강제하여 우발적인 데이터 손실을 막습니다.
필수 인덱스
MySQL은 외래 키 열에 인덱스를 요구합니다. 인덱스가 없으면 InnoDB가 자동으로 만듭니다.외래 키 검사 확인 및 비활성화
대량 데이터 로드 중에는 외래 키 검사가 모든 삽입을 느리게 합니다. 일시적으로 비활성화하세요:기존 외래 키 보기
자주 묻는 질문
외래 키가 성능을 해치나요?
자식 테이블에 대한 모든 INSERT는 부모 테이블에 대한 검사(인덱스 조회)를 촉발합니다. 부모 테이블에서의 모든 DELETE는 자식 행에 대한 검사를 촉발합니다. 처리량이 높은 테이블에서는 이 검사들이 쌓입니다. 쓰기 처리량을 우선하는 팀은 대신 애플리케이션 계층에서 참조 무결성을 강제하는 경우가 많습니다. 어느 선택도 보편적으로 옳지는 않습니다 — 트레이드오프는 데이터베이스 수준의 안전성과 쓰기 성능 사이에 있습니다.기존 테이블에 외래 키를 추가할 수 있나요?
예,ALTER TABLE로 가능합니다:
orders의 기존 행에 customers에 존재하지 않는 customer_id 값이 있으면 ALTER TABLE이 실패합니다. 먼저 데이터를 고치세요.
MySQL은 왜 외래 키에 대해 인덱스를 자동으로 만드나요?
InnoDB는 부모 행이 삭제되거나 갱신될 때 자식 행을 빠르게 검사해야 합니다. FK 열에 인덱스가 없으면 그 검사에 자식 테이블의 전체 테이블 스캔이 필요합니다. 자동 생성된 인덱스가 그것을 막습니다. 먼저 (의미 있는 이름으로) 자체 인덱스를 만들면 InnoDB는 두 번째 인덱스를 만드는 대신 그것을 사용합니다.문제 해결
함께 보기
- MySQL의 정규화 — 외래 키가 강제하는 스키마 설계
- MySQL의 트랜잭션 — 외래 키 검사는 트랜잭션 안에서 일어납니다
- MySQL JOIN 성능과 흔한 실수 — 외래 키가 정의하는 관계에 인덱스 만들기
- MySQL의 소프트 삭제 — 캐스케이드가 소프트 삭제를 무시하는 이유
- MySQL INNER JOIN — 이 관계들을 가로질러 쿼리하는 튜토리얼 레슨
- MySQL 조인의 동작 방식 — 애초에 데이터가 여러 테이블로 나뉘는 이유