-
MySQL - 외래키(Foreign Key)를 써야할까?Spring Boot/DB 2024. 8. 14. 01:46
배경
- 첫회사에서는 외래키가 DB의 성능 저하, 확장을 어렵게 만들고, 유연성을 잃게 만든다고 배웠다.
- 이직한 회사에서는 외래키가 제공하는 정합성, 무결성 유지 편익이 외래키가 없는 것 보다 크다고 배웠다.
- 외래키 없이 1년, 외래키 사용하며 1년을 보내며 느낀점을 남겨본다.
외래키를 쓰지 않는 이유
- 관계형 DB에 관계가 단순할때는 문제가 없지만, 복잡한 관계를 맺으면 문제가 생긴다.
- 기본적으로 FK는 인덱스이다. UPDATE, DELETET시 외래키로 인해 성능 저하가 생긴다.
- 부모테이블, 자식테이블 모두 해당 컬럼 인덱스 생성이 필요하고, 변경 시 부모/자식 테이블 데이터 체크 과정이 필요하여 잠금이 발생한다.
- 데드락의 원인이 된다.
- (참고 : https://martin-son.github.io/Martin-IT-Blog/mysql/foreign%20key/performance/2022/02/28/foreign-key-Performance.html)
- 확장성, 유연성이 좋지 못하다.
- 설계 수정 같은 것을 하고 싶을때 병목이 된다.
- 데이터베이스 schema 마이그래이션, 샤딩 할때 방해가 된다.
- 관계가 명확하다면 문제가 없겠지만, 외래키가 복잡하게 얽힌 경우에 수동으로 데이터 적재나 변경 관리작업 실수를 유발한다.
- 샤딩이나 데이터 축출, 테스트 하고 싶을때 FK가 병목을 일으킨다.
- FK가 있으면 Online Schema Migration을 할 수 없다.
- (참고: 3년간 깃허브에서 FK 없이 근무한 shlomi-noach의 comment - https://github.com/github/gh-ost/issues/331)
- 운영 대응
- 운영대응시 FK cascade가 걸려 있으면 원치 않는 데이터가 삭제되는 대참사가 일어날 수 있다.
- 테이블 관계가 복잡한 경우 긴급한 조치가 필요한데 외래키 문제로 빠른 대응을 못할 수 있다.
- Mysql에 SET foreign_keu_checks=OFF; 로 설정하면 외래키 제약을 잠시 멈출 수 있다. 그러나 다시 활성화 할때 관계를 맞춰주는 작업이 필요한데 까다로울 수 있다. 또한 옵션을 비활성화 동안 on delete cascade, on update cascade 같은 기능이 동작하지 않는다.
- (참고: 인프런 실무에서 왜 외래키 안쓰나요? https://www.inflearn.com/community/questions/629396/%EC%8B%A4%EB%AC%B4%EC%97%90%EC%84%9C-%EC%99%B8%EB%9E%98%ED%82%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%9D%B4%EC%9C%A0%EA%B0%80-%EA%B6%81%EA%B8%88%ED%95%A9%EB%8B%88%EB%8B%A4)
결론
- 기본적으로 외래키를 사용하지 않고 필요한 테이블에만 인덱스 또는 FK를 만들어 사용하는 것이 좋다.
- 외래키가 주는 편익도 분명 크다.
- 경험상 FK를 걸어도 정합성이 깨지는 곳은 깨진다.
- 개발시 Validation을 최대한 꼼꼼하게 하여 불변식을 지킨다. (Domain단 또는 Controller단)
- 단, 외래키 없이 사용하고자 한다면 모든 Table에 audit 데이터를 남긴다. (createdAt, lastModifiedAt, 필요시 작성자, 수정자도) 또한 모든 테이블은 soft delete 상태 값을 가진다. (그래야 추적이 될 것 같다.)
- 특히 초기 스타트업이라면 피봇팅으로 인해 설계가 변경될 일이 빈번하여 FK가 없는 편이 좋다고 생각한다.
- JPA 연관관계도 맺지 않고 유연하게 데이터를 관리한다.
- (JPA ManyToOne의 Many는 few지 Many가 아니다. 운영하며 데이터가 쌓이고 few가 확정되면 그때 JPA 연관관계를 맺어도 늦지 않다. 라고 Hibernate쪽에서 유명한 분이 하신 말에 동의한다. https://vladmihalcea.com/)
반응형'Spring Boot > DB' 카테고리의 다른 글
MySQL 관련해 신경쓰면 좋은 것 (feat. 성능) (0) 2024.11.13 Kafka 기본개념 정리 (0) 2024.04.16 DB Replication이란? 사용 이유 (0) 2024.03.19 [DB] UUID를 고유 값이나 Key로 사용하면 안되는 이유 (0) 2023.06.30 [DB] ACID란? Transaction이란? (0) 2023.06.28