이해

Foreign Key에 대하여

일일일코_장민기 2024. 5. 12. 22:23
728x90

Foreign Key

- 특정 칼럼(들)의 값이 다른 테이블의 특정 row와 매칭되어야 하는 제약 조건

--> 매칭되지 않으면 생성될 수 없기 때문에 두 테이블 사이에 참조 무결성을 유지할 수 있음

 

Foreign Key의 장점

- 데이터 무결성

- 쉬운 데이터 구조 및 관계 확인

- update, delete 등의 로직 간소화

 

Foreign Key의 단점

- 참조 테이블들을 스캔할 때 드는 추가 코스트(insert / update)

- 테이블 구조 변경 시 고려해야 할 사항 증가

- 데이터 변경이 잦을 때 코스트 증가

- 테스트의 번거로움

 

이에 대해 여러 의견을 살펴보았다.

 

O Foreign Key 사용을 지향해야 한다

- 성능이 느려지는 문제(특히 대량의 데이터 로딩)는, 로딩 전에 Foreign Key 를 disable 시켰다가 로딩후 다시 enable을 하면 해결된다.

- 기존 데이터가 FK에 맞지 않아 달 수 없는 문제는, Foreign Key 를 달 때(또는 Alter 명령으로 Enable 시킬 때) Enable Novalidate 옵션으로 생성해 주면 해결

( 디폴트는 Enable Validate 인데 의미는 기존 데이터들에 대해 Validation 검사수행 후 성공하면 Enable 시킨다)

( Enable Novalidate 는 기존 데이터들에 대한 Validation 검사를 수행하지 않고 Foreign Key 를 Enable 시키므로 이 문제를 회피할 수 있다)

- 개발할 때 Foreign Key 가 있으면 불편한 문제는 개발기간 중엔 Foreign Key 를 Disable시키고(부모테이블 없이 자식테이블 테스트 가능), Foreign Key 를 만들 때 Deferred 옵션으로 만들면 된다( 트랜잭션 안에서 부모테이블과 자식테이블의 관계에 따라 DML 작업의 순서가 필요하지 않음)

( 디폴트는 Not Deferred로 문장단위로 검사한다는 뜻이다. 즉 매 문장(Insert, Update, Delete) 마다 검사하기 때문에 순서가 맞지 않으면 오류가 발생한다.)

( Deferred 는 Commit 할 때 검사를 수행하므로 문장들의 순서는 상관없다)

 

O Foreign Key 사용을 지양해야 한다

- DBA 입장에선 간혹, 장애 상황같이 긴급한 상황에서 DDL이나 DML 작업을 바로 수행해야 하는 경우가 발생한다

( 그럴 때 외래키가 있으면 작업에 방해돼서 바로 조치할 수 있는 것도 시간이 두 배 세 배 걸릴 수 있다 )

- 외래키를 사용하지 않아도 JPA에서 ManyToOne 같은 매핑은 사용할 수 있다.

( 굳이 DB에 부담을 줄 필요가 없다 )

- 한정된 자원을 효율적으로 사용해야 하는데 관리할 포인트가 증가하는 것은 분명한 마이너스 포인트

( 한정된 자원으로 최적의 인덱싱을 찾아야 하고, 데이터의 변경에 민감하게 대응해야 하는 상황에서는 FK를 설정하는 것이 효율적이지 못하다 )

- DB 설계가 변경될 경우, 훨씬 더 큰 수정 개발이 야기된다.

- 데드락의 위험

( 실시간으로 몇천 건, 많게는 몇만 건의 데이터가 업데이트 및 동기화되는 상황에서 테이블의 Lock이 여러 테이블로 전파될 위험성 )

- 실시간으로 변동되는 대용량 데이터 베이스, 특히 타 시스템과의 동기화가 이루어지고 있는 산군의 데이터베이스에는 적합하지 않음

- 적절한 조치를 통해 성능 이슈를 해결할 수 있다는 것은 적절한 조치라는 작업을 요구함(코스트 증가)

더보기

"FK의 스캔 코스트가 성능에 큰 영향이 없다", 혹은 "적절한 인덱싱으로 스캔 코스트를 관리할 수 있다."라는 상황 자체가 참조 테이블의 인덱스를 전제한다. FK만을 위한 인덱스를 참조된 테이블에 추가하거나, 참조된 테이블에 업데이트나 삭제가 발생하여 참조하는 테이블에서 이전 값을 조회하기 위해 역스캔하는 경우의 코스트를 줄이기 위해 인덱스를 추가해야 하는 상황이 발생

 

 

개인적으로 Foreign Key를 좋아하지는 않지만 데이터 정합성을 굉장히 중요하다고 생각한다. 하지만 DB에서 FK를 지정하지 않아도 데이터 정합성을 지킬 수 있다면 그렇게 하는 것이 더 낫지 않을까 하는 입장이다(MantToOne 등)

특히 실시간으로 변동되는 대용량 DB가 많은 오늘날에는 조금 맞지 않는 방법은 아닐까 싶다.

물론 데이터 정합성이 매우 강하게 요구되는 경우에는 사용해야 할 것이다.(그런 경우는 실시간 변동이 적기도 할 것 같다)

'이해' 카테고리의 다른 글

엔티티와 레코드  (0) 2024.05.06
JDK와 JRE  (0) 2024.05.04
모듈이란?  (0) 2024.05.04
클린 코드  (0) 2024.04.30
간단한 IT 용어 정리(프로토콜/HTTP/아키텍처/REST)  (0) 2024.04.30