[RDB] Foreign Key 사용 여부 판단
- basic/데이터베이스
- 2022. 6. 19.
시간이 없으시면, 요약만 읽으셔도 좋습니다.
내 생각(요약)
FK를 사용하거나/사용하지 않고 테이블간의 관계를 고려하는 것이 둘 다 많이 사용되는 방법인데,
굳이 하나를 꼽자면 FK를 평소에 사용하지 않고, 정합성이 매우 중요한 곳이라면 FK를 고려할 것입니다.
대신 DB가 아닌 코드 레벨에서 무결성 체크를 잘 해줘야 합니다.
FK 도입 여부를 결정할 때 가장 중요한 사항 고려 사항은 개발 편의성 / 정합성의 tradeoff 라는 결론입니다.
이렇게 생각한 판단 근거는 네 가지 입니다(DB 처리속도, 개발 편의성, 개발자의 지식 커버리지, 정합성)
1) DB 처리속도는 FK를 걸었을 때 약간 느리거나 큰 차이 없고,
2) FK가 있으면, 마이그레이션이나 설계 변경이 힘들 수 있음, 테스트 데이터를 만드는 것이 어려움
3) 어느 정도 규모가 있는 회사에서는 DBA와 개발자의 역할이 나누어져 있어서, DBA가 어떻게 DB를 세팅했는지 모를 수 있음. 따라서 FK의 영향을 개발자가 평가하기 어려울 수 있음
4) FK를 사용하지 않더라도 충분히 정합성 검증이 가능한지
디테일
1. 속도에 대한 판단 => 속도는 큰 고려사항이 아님
[FK가 걸려있는 경우 참고하는 항목들]
a. 자식테이블에 INSERT 할 때 참조키가 부모테이블에 있는지
b. 자식테이블에서 참조키를 UPDATE할 때 변경 후 값이 부모테이블에 있는지
c. 부모테이블에서 DELETE할 때 자식테이블에서 참조하고 있는지
만약 DB에서 저장 구조가 B+ Tree 구조라면
https://en.wikipedia.org/wiki/B+_tree
단일 테이블에 대한 각 연산들의 Big-O는 다음과 같습니다.
INSERT에 O(log N)
UPDATE시에 O(log N)
DELETE시에 O(log N)
FK가 존재한다면
자식테이블에서 INSERT에 O(log N * log N)
자식테이블에서 UPDATE시에 O(log N * log N)
부모테이블에서 DELETE시에 O(log N * N) ...?
만약 DELETE가 FK가 걸린 자식 항목들을 각각 찾는다면, log N 연산을 N번 하기 때문에
FK가 많이 걸려 있다면 큰 부하지점이 될 수 있을 듯 보입니다.
하지만 일반적인 연산이 아니기 때문에 속도측면에서는 큰 영향이 없을 듯 합니다.
(참고: https://okky.kr/article/586565)
FK의 대상이 되는 테이블의 인덱스가 잘 걸려있다고 하면 O(log N) 만큼 걸리는 것으로 알고 있고
그렇다면 10^10건의 데이터가 있다고 하면 log(2) 10^10 = 33이니 33회 정도와 비슷한 오더로 연산을 더 하는 셈일텐데
insert에서 큰 차이가 있을까 하는 생각도 들긴 합니다.
2. 개발 편의성의 판단
불편할 수 있는 부분은 다음과 같습니다.
- 마이그레이션시에 제약 사항 때문에 쉽게 테이블 변경을 할 수 없으니, 불편할 수 있습니다.
- DML 쿼리를 날릴 때, 부모 쿼리부터 날려야 함(관련 블로그)
- 테스트 데이터 생성
FK가 걸려있으면, 자식 테이블 테스트 데이터를 생성하면서 부모 테스트 데이터도 생성해야 하니
간단한 테스트도 복잡해집니다. 이에 대한 우회 방법도 있다고 하지만(관련 블로그),
처음부터 FK를 걸지 않으면 아예 우회를 할 필요가 없기 때문에 굳이 걸지 않아도 괜찮다고 생각됩니다.
3. 개발자의 지식 커버리지
자바 관련 오픈 카톡방 대화 내용(등장인물 A, B, C 모두 FK 사용하지 않는 입장입니다)
[A] INSERT도 INSERT인데 FK가 걸려있으면 마이그레이션이나 테이블 구조 바꾸는 등 작업할 때 아예 불가능하거나 테이블에 락이 걸려서 속도가 엄청나게 느려질 수 있죵
그리고 무엇보다 핵심적으로 요즘은 DB는 DBA가 관리하고 코드는 개발자들이 관리하는데 모든 개발자들이 DB의 논리적, 물리적 설정까지 파악할 수 있을까~라는 의문이 들긴 하네요
슬로우 쿼리 나가거나 DB CPU Utilization 증가하면 가장 먼저 파악하시는 것도 DBA분들이시기 때문에.. 암만 그 구조를 다 안다고 해도 발생할 수 있는 문제를 예상하고 문제가 발생했을 때 파악하는건 그분들이 훠어얼씬 잘하시죵
[B] 근데 DBA라는 직군이 큰 회사 아니고선 잘 없는 포지션이기도 한데
[A] 그럼 여기서 이런 의문이 생기는거져. '내가 짠 코드에서 발생할 수 있는 문제도 예상 못하는데 DB의 문제를 예상할 수 있을까?'
[B] 정합성은 어플리케이션 영역에서도 충분히 처리가 가능하죠. 요즘은 FK를 걸지않고 ERD상에서 논리적으로 관계만 표현해두죠
옛날처럼 DB에서 모든걸 다 위임하고 처리할 필요는 없죠
[A] 제가 알기론 마이크로소포트쪽은 FK 기반으로 한 쿼리/DB 지향적인 구조로 된 플젝이 많은걸로 알고, 은행쪽은 시스템 자체가 가장 코어에 있는건 MSA가 불가능해서 모놀리틱에다가 테이블 한개에 컬럼 수백개 박혀있는 구조도 있어서 FK같은거 쓰는걸로 알고 있습니당~
저희 회사는 돈을 다루긴하는데 애플리케이션 레벨에서 다 매니징하고 FK 안씁니다.
데이터 정합성 깨질일도 많이 없고 깨지는 경우는 연동하는 서버/제휴사의 오류로 네트워크 타임아웃 났을때 밖에 없는데 그런 경우 최대한 고객의 이익을 우선으로 생각하여 서비스 자체가 설계되고 있어서 고객이 피해를 입지 않을뿐더러 거의 초단위로 자동으로 정합성 보정하는 시스템이 각 서비스마다 있습니다.
[B] MSSQL쓰는곳은 전부다 모든처리를 DB에서 하더라구요. 제가 Si했을시절에 MSSQL 쓰는 고객사쪽 가보면 전부...그리고 죄다 프로시저 쓰고
타 DB는 그냥 SQL짜는데 유독 MSSQL만 프로시저껍데기 씌워서 처리하는데 그이유를 몰겠...ㅋㅋ
[C] 그냥 그 고객사가 그런거 아님?
우연히 4군데가 다 그런걸수도
4. 정합성
이 부분은 금융권에서도 FK없이 시스템을 구축한다는 것을 볼 수 있지만(관련 블로그, 3번 카카오톡 대화 참조)
사용하는 경우에 어떻게 정합성을 담보할 수 있을지 best practice를 좀 더 조사하는 것이 좋을 듯 합니다.
결론 - 기본적으로 FK없이 가지만, 정합성이 필요한 부분에는 FK 사용
속도 - 비슷함
개발 편의성 - FK가 없는 것이 좋음
개발자의 지식 커버리지 - FK가 없는 것이 지식이 덜 필요함
정합성 - 금융권에서도 FK 없이 프로젝트 진행하는 경우도 많아서, practice가 쌓이고 있다고 생각됨
정합성만 담보된다면 FK가 없어도 되는데, 최근 트렌드가 FK 없이도 충분히 확보할 수 있다는 느낌이고,
좀 더 best practice들에 대한 근거가 필요할 것 같습니다.
참고할만한 사항
김영한님 강의 내용(스프링부트-JPA-활용-1, 엔티티 클래스 개발2 내용 중)
- 정합성 보다는 빠른처리가 요구되는 경우(예를 들어, 게임 데이터)
FK를 안 거는 것이 좋음
- 빠른처리보다는 정합성이 중요한 경우(예를 들어, 은행 데이터)
FK를 거는 것이 좋음
참고할만한 글들
FK 찬성
- https://okky.kr/article/586565
FK 반대:
- 카카오톡 대화
FK 중립:
- 인프런 김영한님 강의 내용(스프링부트-JPA-활용-1, 엔티티 클래스 개발2 내용 중)
'basic > 데이터베이스' 카테고리의 다른 글
python으로 스키마 정보 없이 sqlite3 데이터 읽기 (0) | 2019.08.01 |
---|