it-swarm-ko.tech

외래 키에 어떤 문제가 있습니까?

Joel Spolskypodcast 014 에서 언급 한 바에 따르면 외래 키를 거의 사용하지 않았다고 들었습니다. 그러나 필자는 데이터베이스 전체에서 중복 및 후속 데이터 무결성 문제를 피하는 것이 매우 중요합니다.

사람들이 이유에 대해 확실한 이유가 있습니까 (스택 오버플로 원칙에 따라 토론하지 않기 위해)?

편집 : "아직 외래 키를 만들 이유가 없었으므로 이것이 첫 번째 이유 일 수 있습니다. 실제로 설정하려면 "

247
ljs

외래 키를 사용하는 이유 :

  • 당신은 고아 행을 얻을 수 없습니다
  • 캐스케이드 삭제시 동작이 훌륭해 자동으로 테이블 정리
  • 데이터베이스의 테이블 간 관계를 알면 옵티마이 저가 조인 카디널리티에 대한 더 나은 추정치를 얻을 수 있으므로 쿼리가 가장 효율적인 실행을 위해 쿼리를 계획하는 데 도움이됩니다.
  • FK는 데이터베이스에서 수집해야 할 통계가 가장 중요한 힌트를 제공하여 성능이 향상됩니다.
  • 그들은 모든 종류의 자동 생성 지원을 가능하게합니다 .ORM은 스스로 생성 할 수 있으며 시각화 도구는 멋진 스키마 레이아웃을 만들 수 있습니다.
  • 암묵적 관계가 명시 적으로 문서화되어 있기 때문에 프로젝트를 처음 접하는 사람이 사물 흐름에 더 빨리 들어갈 수 있습니다.

외래 키를 사용하지 않는 이유 :

  • fK 일관성을 확인해야하기 때문에 모든 CRUD 작업에서 DB 작업을 추가로 수행하고 있습니다. 이탈이 많은 경우 큰 비용이 될 수 있습니다.
  • fK는 관계를 적용함으로써 사물을 추가/삭제해야하는 순서를 지정하므로 DB가 원하는 것을 거부 할 수 있습니다. (이러한 경우, 고아 행을 작성하는 것이 일반적이며 좋지 않습니다.) 대규모 배치 업데이트를 수행 할 때 특히 고통스럽고 두 번째 테이블이 일관된 상태를 만드는 상태에서 한 테이블을 다른 테이블보다 먼저로드합니다 (하지만 두 번째로드가 실패하고 데이터베이스가 일치하지 않습니까?).
  • 때로는 데이터가 더러워 질 것이라는 것을 미리 알고, 동의하고, DB가 그것을 받아들이기를 원합니다
  • 당신은 단지 게으르고 있습니다 :-)

나는 대부분의 확립 된 데이터베이스가 적용되지 않고 외래 키를 지정하는 방법을 제공한다고 생각합니다 (확실하지 않습니다!). 비 집행은 FK를 사용하지 않는 모든 이유를 없애기 때문에 두 번째 섹션의 이유 중 하나라도 해당되는 경우 해당 경로를 사용해야합니다.

344
SquareCog

이것은 육성 문제입니다. 교육 또는 직업 경력의 어느 곳에서 데이터베이스를 먹이고 돌보는 데 시간을 보냈거나 (또는 ​​재능있는 사람들과 긴밀히 협력 한 경우), 사고 과정에서 실체와 관계의 기본 교리가 잘 제한되어 있습니다. 이러한 기초 중 하나는 데이터베이스에서 키를 지정하는 방법/언제/이유 (1 차, 외래 및 대체)입니다. 두 번째 본성입니다.

그러나 RDBMS 관련 노력으로 과거에 철저하거나 긍정적 인 경험을하지 않았다면 그러한 정보에 노출되지 않았을 가능성이 있습니다. 또는 과거에 데이터베이스가 우연히 안티 바이러스 환경 인 환경에 몰입 한 적이있을 수 있습니다 (예 : "DBA는 바보입니다. 적은 시간에 우리는 Java/c # 코드 슬링거가 하루를 절약 할 수있는 적은 몇 가지를 선택했습니다"). 그냥 들으면 FK (그리고 그들이 암시 할 수있는 제약)가 정말로 중요하다는 것을 알려주는 일부 dweeb의 비전에 대한 비웃음.

대부분의 사람들은 그들이 어렸을 때 양치질이 중요하다는 것을 배웠습니다. 당신은 그것없이 얻을 수 있습니까? 물론, 어딘가에 줄을 서서 식사 할 때마다 닦았을 때보 다 치아가 적습니다. 엄마와 아빠가 구강 위생뿐만 아니라 데이터베이스 디자인을 다루는 데 충분한 책임이 있다면, 우리는이 대화를하지 않을 것입니다. :-)

79
Ed Lucas

나는 당신이 그것을 벗어날 수있는 많은 응용 프로그램이 있다고 확신하지만 최선의 아이디어는 아닙니다. 데이터베이스를 올바르게 관리하기 위해 항상 응용 프로그램을 사용할 수는 없으며 솔직히 데이터베이스를 관리하는 것이 응용 프로그램에 큰 관심을 가져서는 안됩니다.

relational 데이터베이스를 사용하는 경우 relationships 데이터베이스가 정의되어 있어야합니다. 불행히도 이러한 태도 (외래 키가 필요하지 않음)는 데이터 무결성과 같은 어리석은 일에 신경 쓰지 않는 많은 응용 프로그램 개발자가 수용하는 것처럼 보입니다 (그러나 회사에 전용 데이터베이스 개발자가 없기 때문에 필요합니다). 일반적으로 이러한 유형으로 구성된 데이터베이스에서는 기본 키만 있으면 운이 좋습니다.)

52
AlexCuse

외래 키는 관계형 데이터베이스 모델에 필수입니다.

40
Galwegian

항상 사용하지만 금융 시스템 용 데이터베이스를 만듭니다. 데이터베이스는 응용 프로그램의 중요한 부분입니다. 재무 데이터베이스의 데이터가 완전히 정확하지 않은 경우 실제로 코드/프런트 엔드 디자인에 얼마나 많은 노력을 기울이고 있는지는 중요하지 않습니다. 당신은 단지 시간을 낭비하고 있습니다.

또한 여러 시스템이 일반적으로 데이터를 읽는 다른 시스템 (Crystal Reports)에서 데이터를 삽입하는 시스템 (내가 디자인 한 API를 사용할 필요는 없음)에 이르기까지 데이터베이스와 직접 인터페이스해야한다는 사실도 있습니다. VBScript를 발견하고 SQL 상자에 대해 SA 암호를 가진 둔한 관리자). 데이터베이스가 가능한 한 바보 같은 증거가 아닌 경우에는 데이터베이스를 사용하십시오.

데이터가 중요하다면 외래 키를 사용하고 데이터와 상호 작용하는 저장 프로 시저 모음을 만들고 가능한 가장 어려운 DB를 만드십시오. 데이터가 중요하지 않은 이유는 무엇입니까?

29
Ant

Update : 나는 항상 항상 외래 키를 사용합니다. "복잡한 테스트"라는 이의 제기에 대한 나의 대답은 "단위 테스트를 작성하여 데이터베이스가 전혀 필요하지 않습니다. 데이터베이스를 사용하는 모든 테스트는 올바르게 사용해야하며 외래 키도 포함됩니다. 설정이 어려운 경우, 설치하는 데 덜 고통스러운 방법을 찾으십시오. "


외래 키는 자동화 된 테스트를 복잡하게합니다

외래 키를 사용한다고 가정합니다. "금융 계정을 업데이트 할 때 거래 기록을 저장해야합니다."라는 자동 테스트를 작성하고 있습니다. 이 테스트에서는 accountstransactions의 두 테이블에만 관심이 있습니다.

그러나 accounts에는 contracts에 대한 외래 키가 있고 contracts에는 fk ~ clients이 있으며 clients에는 fk ~ cities, cities에는 fk ~ states이 있습니다.

이제 데이터베이스는 테스트와 관련이없는 4 개의 테이블에 데이터를 설정하지 않고 테스트를 실행할 수 없습니다 .

이에 대한 두 가지 가능한 관점이 있습니다.

  • "이것은 좋은 일이다. 테스트는 현실적이어야하고, 이러한 데이터 제약은 프로덕션에 존재할 것이다."
  • "이것은 나쁜 일이다. 다른 부분을 포함하지 않고 시스템의 부분을 테스트 할 수 있어야한다. 시스템에 대한 통합 테스트를 전체적으로 추가 할 수있다."

테스트를 실행하는 동안 외래 키 검사를 일시적으로 해제 할 수도 있습니다. 적어도 MySQL은 지원 .

19
Nathan Long

"레코드 삭제가 더 번거로워 질 수 있습니다. 다른 테이블에 외래 키가 해당 제약 조건을 위반하는 레코드가있는"마스터 "레코드는 삭제할 수 없습니다."

SQL 표준은 외래 키가 삭제되거나 업데이트 될 때 수행되는 동작을 정의한다는 점을 기억해야합니다. 내가 아는 것은 :

  • ON DELETE RESTRICT-이 열에 키가있는 다른 테이블의 행이 삭제되지 않도록합니다. 이것이 Ken Ray가 위에서 설명한 것입니다.
  • ON DELETE CASCADE-다른 테이블의 행이 삭제되면이 테이블에서이를 참조하는 행을 삭제하십시오.
  • ON DELETE SET DEFAULT-다른 테이블의 행이 삭제되면이를 참조하는 외래 키를 열의 기본값으로 설정하십시오.
  • ON DELETE SET NULL-다른 테이블의 행이 삭제되면이 테이블에서이를 참조하는 외래 키를 null로 설정하십시오.
  • ON DELETE NO ACTION-이 외래 키는 외래 키임을 표시합니다. 즉 OR 매퍼에 사용됩니다.

이와 동일한 동작이 ON UPDATE에도 적용됩니다.

기본값은 사용중인 sql 서버에 따라 다릅니다.

14
Powerlord

@ imphasing-이것은 유지 보수의 악몽을 일으키는 사고의 종류입니다.

왜 오, 왜 선언적 참조 무결성을 무시하고 데이터가 최소한 일관성이있을 수있는 곳에서 보장 최소한의 예방 조치 인 소위 "소프트웨어 시행"을 선호합니다.

14
Ed Guiness

그것들을 사용하지 않는 한가지 좋은 이유가 있습니다 : 그들의 역할이나 사용법을 이해하지 못하는 경우

잘못된 상황에서 외래 키 제약으로 인해 사고의 폭포 복제가 발생할 수 있습니다. 누군가 잘못된 레코드를 제거하면 실행 취소하면 엄청난 작업이 될 수 있습니다.

반대로, 무언가를 제거해야 할 때, 제대로 설계되지 않은 경우 제약 조건으로 인해 모든 종류의 잠금이 발생할 수 있습니다.

12
Kent Fredric

good 이유가 없습니다 not ... 고아 행이 큰 문제가 아닌 한 .

11
Matt Rogish

더 큰 질문은 : 눈가리개로 운전하겠습니까? 참조 제한이없는 시스템을 개발하는 것이 바로 그런 방법입니다. 비즈니스 요구 사항 변경, 응용 프로그램 디자인 변경, 코드 변경에 대한 각각의 논리적 가정, 논리 자체가 리팩터링 될 수 있습니다. 일반적으로 데이터베이스의 제약 조건은 현대 논리 가정하에 배치되며 특정 논리 주장 및 가정에 대해 올바른 것으로 보입니다.

응용 프로그램의 수명주기를 통해 참조 및 데이터 검사는 특히 새로운 요구 사항으로 인해 논리적 응용 프로그램 변경이 발생하는 경우 응용 프로그램을 통해 경찰 데이터 수집을 제한합니다.

이 리스팅의 주제에 대해-외래 키 자체가 "성능 향상"이 아니거나 실시간 트랜잭션 처리 시스템의 관점에서 "성능 저하"가 아닙니다. 그러나 대용량 "배치"시스템에서는 제약 조건 검사에 대한 총 비용이 있습니다. 여기에 실시간과 배치 트랜잭션 프로세스의 차이점이 있습니다. 배치 처리-제약 조건 검사에 의해 발생 된 순차적으로 처리 된 배치의 막대한 비용으로 인해 성능이 저하되는 경우.

잘 설계된 시스템에서, 데이터 일관성 검사는 일괄 처리를 "이전에"수행 할 수 있습니다 (그럼에도 불구하고 여기에도 관련 비용이 있습니다). 따라서로드 시간 동안 외래 키 제약 조건 검사가 필요하지 않습니다. 실제로 배치를 처리 할 때까지 외래 키를 포함한 모든 제약 조건을 일시적으로 비활성화해야합니다.

QUERY PERFORMANCE-테이블이 외래 키에 조인 된 경우 외래 키 열이 INDEXED가 아님을 인식해야합니다 (각 기본 키는 정의에 의해 색인화 됨). 이 문제를 위해 외래 키를 색인화하면 키를 색인화하고 색인에서 테이블을 조인하면 색인화되지 않은 키를 외래 키 제약 조건으로 조인하는 것이 아니라 성능을 향상시킬 수 있습니다.

피사체 변경, 데이터베이스가 웹 사이트 표시/렌더링 콘텐츠 등을 지원하고 클릭을 기록하는 경우 모든 테이블에 대한 전체 제약 조건이있는 데이터베이스가 이러한 목적으로 종료됩니다. 생각 해봐 대부분의 웹 사이트는 데이터베이스를 사용하지 않습니다. 데이터가 방금 기록되고 언급되지 않은 유사한 요구 사항의 경우, 제약이없는 인 메모리 데이터베이스를 사용하십시오. 이것은 데이터 모델이없고 논리 모델이 있지만 물리적 데이터 모델이 없다는 것을 의미하지는 않습니다.

4
jasbir L

내 경험상 데이터베이스 크리티컬 애플리케이션에서 FK를 사용하지 않는 것이 좋습니다. 나는 FK가 좋은 습관이지만 데이터베이스가 크고 CRUD 작업/초가 큰 곳에서는 실용적이지 않다고 말하는 사람들에 동의하지 않을 것입니다. 이름 없이도 공유 할 수 있습니다. 가장 큰 투자 은행 중 하나는 데이터베이스에 단일 FK가 없습니다. 이러한 제약은 프로그래머가 처리하며 DB와 관련된 응용 프로그램을 만듭니다. 기본적인 이유는 새로운 CRUD가 완료 될 때마다 여러 테이블에 영향을 미치고 각 삽입/업데이트에 대해 확인해야하지만 단일 행에 영향을주는 쿼리에는 큰 문제는 아니지만 처리 할 때 큰 대기 시간이 발생하기 때문입니다. 모든 대형 은행이 일상적인 작업으로 수행해야하는 일괄 처리.

FK를 피하는 것이 좋지만 프로그래머가 위험을 처리해야합니다.

3
Rachit

"레코드를 추가하기 전에 해당 레코드가 다른 테이블에 있는지 확인하십시오"는 비즈니스 논리입니다.

데이터베이스에서 이것을 원하지 않는 몇 가지 이유는 다음과 같습니다.

  1. 비즈니스 규칙이 변경되면 데이터베이스를 변경해야합니다. 데이터베이스는 많은 경우 인덱스를 다시 작성해야하며 이는 큰 테이블에서 느립니다. 변경 규칙에는 손님이 댓글을 올리더라도 메시지를 게시하거나 사용자가 자신의 계정을 삭제할 수 있도록하는 등이 포함됩니다.

  2. 데이터베이스를 변경하는 것은 변경 사항을 프로덕션 저장소로 푸시하여 소프트웨어 수정 사항을 배치하는 것만 큼 쉽지 않습니다. 데이터베이스 구조를 가능한 많이 변경하지 않기를 원합니다. 데이터베이스에 비즈니스 로직이 많을수록 데이터를 변경하고 재 인덱싱을 트리거해야 할 가능성이 높아집니다.

  3. TDD. 단위 테스트에서는 모의 데이터베이스를 대체하고 기능을 테스트 할 수 있습니다. 데이터베이스에 비즈니스 로직이있는 경우 완전한 테스트를 수행하지 않고 테스트 목적으로 데이터베이스를 테스트하거나 코드에서 비즈니스 로직을 복제하여 로직을 복제하고 로직이 작동하지 않을 가능성을 증가시켜야합니다. 같은 길.

  4. 다른 데이터 소스로 논리 재사용 데이터베이스에 논리가 없으면 내 응용 프로그램은 데이터베이스의 레코드에서 개체를 만들고 웹 서비스, json 파일 또는 기타 소스에서 개체를 만들 수 있습니다. 데이터 매퍼 구현을 교체해야하며 모든 비즈니스 로직을 모든 소스와 함께 사용할 수 있습니다. 데이터베이스에 논리가있는 경우 이것이 불가능하며 데이터 매퍼 계층 또는 비즈니스 논리에서 논리를 구현해야합니다. 어느 쪽이든 코드에 해당 검사가 필요합니다. 데이터베이스에 논리가 없으면 다른 데이터베이스 또는 플랫 파일 구현을 사용하여 다른 위치에 응용 프로그램을 배포 할 수 있습니다.

3
Tom B

외래 키를 사용하는 추가 이유 :-데이터베이스를 더 많이 재사용 할 수 있습니다.

외래 키를 사용하지 않는 추가 이유 :-재사용을 줄임으로써 고객을 도구에 고정 시키려고합니다.

3
Dan

이전 답변에 데이터 일관성을 유지하는 데 유용하다는 점에 동의합니다. 그러나 몇 주 전에 표준화되고 일관된 데이터의 장단점을 논의한 Jeff Atwood의 흥미로운 게시물 이있었습니다.

간단히 말해, 대량의 데이터를 처리 할 때 비정규 화 된 데이터베이스가 더 빠를 수 있습니다. 응용 프로그램에 따라 정확한 일관성에 신경 쓰지 않을 수도 있지만 DB와는 달리 데이터를 처리 할 때 훨씬 더 조심해야합니다.

2
Santiago Palladino

Clarify 데이터베이스는 기본 또는 외래 키가없는 상용 데이터베이스의 예입니다.

http://www.geekinterview.com/question_details/18869

재미있는 점은 기술 문서가 테이블이 어떻게 관련되어 있는지, 테이블을 조인하는 데 사용할 열 등을 설명하기 위해 많은 시간을 소비한다는 것입니다.

다시 말해, c 는 명시 적 선언 (DRI)으로 테이블에 조인 할 수 있지만 를 선택하지 않았습니다.

결과적으로 Clarify 데이터베이스는 불일치로 가득 차서 성능이 저하됩니다.

그러나 개발자가 작업을 더 쉽게 만들고 삭제, 추가하기 전에 관련 행을 확인하는 것과 같은 참조 무결성을 처리하기 위해 코드를 작성할 필요가 없다고 생각합니다.

그리고 그것은 관계형 데이터베이스에 외래 키 제약 조건이 없다는 주요 이점입니다. 그것은 적어도 악마를 돌볼 수있는 관점에서 개발하는 것이 더 쉬워집니다.

2
Ed Guiness

Oracle 데이터베이스 만 알고 있으며 다른 데이터베이스는 없으며 외래 키가 데이터 무결성을 유지하는 데 필수적이라고 말할 수 있습니다. 데이터를 삽입하기 전에 데이터 구조를 작성하고 수정해야합니다. 이것이 완료되면 모든 기본 및 외래 키가 생성되고 작업이 완료됩니다!

의미 : 고아 행? 아니, 내 인생에서 본 적이 없어 나쁜 프로그래머가 외래 키를 잊어 버렸거나 다른 수준에서 외래 키를 구현하지 않은 경우. 둘 다 Oracle과 관련하여 큰 실수로 인해 데이터 복제, Orphan 데이터 및 데이터 손상이 발생할 수 있습니다. FK가 적용되지 않은 데이터베이스는 상상할 수 없습니다. 나에게 혼란스러워 보인다. 유닉스 권한 시스템과 비슷합니다. 모두가 루트라고 상상해보십시오. 혼돈을 생각하십시오.

외래 키는 기본 키와 마찬가지로 필수적입니다. 기본 키를 제거하면 어떻게 되나요? 글쎄, 총 혼란이 일어날 것입니다. 그게 다야. 기본 또는 외래 키 책임을 프로그래밍 수준으로 이동할 수 없으며 데이터 수준이어야합니다.

단점? 네 그럼요 ! 삽입시 더 많은 검사가 수행 될 것입니다. 그러나 데이터 무결성이 성능보다 더 중요하다면 당연한 일입니다. Oracle의 성능 문제는 PK 및 FK와 함께 제공되는 인덱스와 관련이 있습니다.

2
tvCa

레코드 삭제가 더 번거로워 질 수 있습니다. 외래 키가 해당 제약 조건을 위반하는 다른 테이블의 레코드가있는 "마스터"레코드는 삭제할 수 없습니다. 트리거를 사용하여 계단식 삭제를 수행 할 수 있습니다.

기본 키를 현명하게 선택하지 않으면 해당 값을 변경하는 것이 훨씬 더 복잡해집니다. 예를 들어, "고객"테이블의 PK를 사람의 이름으로 사용하고 "주문"테이블에서 해당 키를 FK로 만드는 경우 고객이 자신의 이름을 변경하려면 왕관이됩니다 .. 그러나 그것은 단지 데이터베이스 설계의 문제입니다.

Fireign 키를 사용할 때의 이점이 예상되는 단점보다 크다고 생각합니다.

1
Ken Ray

나는 대부분의 의견을 여기에 두어야합니다. 외래 키는 데이터가 무결성을 유지하는 데 필요한 항목입니다. ON DELETE 및 ON UPDATE에 대한 다양한 옵션을 사용하면 사람들이 사용과 관련하여 여기에서 언급 한 "다운 폴트"를 해결할 수 있습니다.

나는 모든 프로젝트의 99 %에서 FK가 데이터의 무결성을 강화해야한다는 것을 알지만, 나쁜 데이터에 관계없이 이전 데이터를 유지 해야하는 클라이언트가있는 드문 경우가 있습니다 .... 그러나 어쨌든 유효한 데이터 만 가져 오는 코드를 작성하는 데 많은 시간을 소비하므로 의미가 없습니다.

1
Mitchel Sellers

내가 들었던 주장은 프론트 엔드에 이러한 비즈니스 규칙이 있어야한다는 것입니다. 외래 키는 처음부터 제약 조건을 위반하는 삽입을 허용하지 않아야 할 때 "불필요한 오버 헤드를 추가"합니다. 이것에 동의합니까? 아뇨,하지만 제가 항상 들었습니다.

EDIT : 내 생각에 그는 외래 키를 개념으로 사용하지 않고 외부 키 제약 조건 을 참조하고 있다고 생각합니다.

1
lordscarlet

외래 키 제약 조건을 확인하려면 CPU 시간이 걸리므로 일부 사람들은 외래 키를 생략하여 추가 성능을 얻습니다.

1
remonedo

당신이 절대적으로 확신한다면, 미래에 하나의 기본 데이터베이스 시스템이 변경되지 않을 것이라고 외래 키를 사용하여 데이터 무결성을 보장 할 것입니다.

그러나 외래 키를 전혀 사용하지 않는 또 다른 아주 좋은 실제 이유는 다음과 같습니다.

다른 데이터베이스 시스템을 지원해야하는 제품을 개발 중입니다.

여러 다른 데이터베이스 시스템에 연결할 수있는 Entity Framework를 사용하는 경우 "오픈 소스 무료"서버리스 데이터베이스를 지원할 수도 있습니다. 이러한 모든 데이터베이스가 외래 키 규칙 (행 업데이트, 삭제 등)을 지원하지는 않습니다.

이것은 다른 문제를 일으킬 수 있습니다 :

1.) 데이터베이스 구조를 만들거나 업데이트 할 때 오류가 발생할 수 있습니다. 데이터베이스 시스템에서 외래 키를 무시하기 때문에 자동 오류 만있을 수 있습니다.

2.) 외래 키를 사용하는 경우 비즈니스 논리에서 데이터 무결성 검사를 거의 또는 전혀 수행하지 않을 수 있습니다. 이제 새 데이터베이스 시스템이 이러한 외래 키 규칙을 지원하지 않거나 다른 방식으로 동작하는 경우 비즈니스 논리를 다시 작성해야합니다.

다른 데이터베이스 시스템이 필요한 사람은 누구입니까? 글쎄, 모든 사람이 자신의 컴퓨터에서 완전히 날아간 SQL-Server를 감당할 수 있거나 원하는 것은 아닙니다. 이것은 유지 관리해야하는 소프트웨어입니다. 다른 사람들은 이미 다른 DB 시스템에 시간과 돈을 투자했습니다. 서버리스 데이터베이스는 한 대의 컴퓨터에서만 소규모 고객에게 적합합니다.

이러한 DB 시스템이 어떻게 작동하는지는 아무도 모르지만 무결성 검사를 통해 비즈니스 로직은 항상 동일하게 유지됩니다.

1
Michael

나는 Dmitriy의 대답을 에코합니다.

FK가 종종 가져 오는 성능 오버 헤드에 대해 걱정하는 사람들을 위해, Oracle에서는 삽입, 삭제 또는 업데이트 중에 제약 조건 유효성 검사의 비용 오버 헤드없이 쿼리 최적화 프로그램 FK 제약 조건을 활용할 수있는 방법이 있습니다. 즉, RELY DISABLE NOVALIDATE 속성을 사용하여 FK 제약 조건을 작성합니다. 이는 쿼리 최적화 프로그램이 데이터베이스가 실제로 제약 조건을 적용하지 않고 쿼리를 작성할 때 제약 조건이 적용되었다는 것을 의미합니다. FK 제약 조건으로 테이블을 채울 때 FK 열에 제약 조건을 위반하는 데이터가없는 것처럼 확실히 확인하려면 책임을 져야합니다. 이 FK 제약 조건이있는 테이블과 관련된 쿼리에서 신뢰할 수없는 결과를 얻을 수 있습니다.

나는 보통이 전략을 내 데이터 마트 스키마의 일부 테이블에서 사용하지만 통합 스테이징 스키마에서는 사용하지 않습니다. 데이터를 복사하는 테이블에 이미 동일한 제약 조건이 적용되었거나 ETL 루틴이 제약 조건을 적용하는지 확인합니다.

1
Mike McAllister

외래 키에 인덱스를 넣는 것을 잊어 버린 특정 조작이 느리다고 불평하는 사람들 로부터이 주장을 들었습니다. 요약하자면 외래 키를 사용하지 않는 좋은 이유는 없습니다. 모든 최신 데이터베이스는 계단식 삭제를 지원하므로 ...

1
Arno

나에게 ACID 표준을 따르고 싶다면 참조 무결성을 보장하기 위해 외래 키를 갖는 것이 중요합니다.

1
CodeRot

여기에 응답하는 많은 사람들이 참조 제한 조건을 통해 구현 된 참조 무결성의 중요성에 너무 매달 렸습니다. 참조 무결성을 가진 큰 데이터베이스에서 작업하는 것은 성능이 좋지 않습니다. Oracle은 계단식 삭제에서 특히 나쁜 것 같습니다. 제 경험에 따르면 응용 프로그램은 데이터베이스를 직접 업데이트해서는 안되며 저장 프로 시저를 통해 이루어져야합니다. 이렇게하면 코드베이스가 데이터베이스 내부에 유지되므로 데이터베이스의 무결성이 유지됩니다.

많은 응용 프로그램이 데이터베이스에 액세스하는 경우 참조 무결성 제약 조건으로 인해 문제가 발생하지만 이는 제어에 달려 있습니다.

응용 프로그램 개발자에게는 데이터베이스 개발자가 반드시 익숙하지 않은 요구 사항이 매우 다를 수 있다는 점에서도 더 큰 문제가 있습니다.

1
Zak

또한 대부분의 데이터베이스에서 외래 키가 필요하다고 생각합니다. 유일한 일관성 (일관성 강화로 인한 성능 저하 외에) 외래 키를 사용하면 사람들이 기능 외래 키가 있다고 가정하는 코드를 작성할 수 있다는 것입니다. 절대 허용되지 않아야합니다.

예를 들어, 사람들이 참조 테이블에 삽입 한 코드를 작성하고 첫 번째 삽입이 성공했는지 확인하지 않고 참조 테이블에 삽입을 시도하는 것을 보았습니다. 외래 키를 나중에 제거하면 데이터베이스가 일치하지 않습니다.

또한 업데이트 또는 삭제시 특정 동작을 가정 할 수있는 옵션이 없습니다. 외래 키가 있는지 여부에 관계없이 원하는 작업을 수행하려면 코드를 작성해야합니다. 삭제되지 않았을 때 연속으로 삭제한다고 가정하면 삭제가 실패합니다. 참조 된 열에 대한 업데이트가 참조 행이 아닌 경우 참조 행에 전파되었다고 가정하면 업데이트가 실패합니다. 코드 작성을 위해 이러한 기능이 없을 수도 있습니다.

이러한 기능이 켜져 있으면 코드가 기능을 에뮬레이트하므로 약간의 성능이 저하됩니다.

따라서 요약 .... 일관된 데이터베이스가 필요한 경우 외래 키가 필수적입니다. 외래 키는 사용자가 작성하는 코드에 존재하거나 기능한다고 가정해서는 안됩니다.

1
Eric

우와 ...
모든 곳에서 답변합니다. 실제로 이것은 내가 본 것 중 가장 복잡한 주제입니다. FK는 필요할 때 사용하지만 프로덕션 환경에서는 거의 사용하지 않습니다.

Fks를 거의 사용하지 않는 이유는 다음과 같습니다.

1. 성능을 향상시키기 위해 작은 서버에서 거대한 데이터를 처리하는 대부분의 시간에는 FK를 제거해야합니다. FK가 있고 RDBMS 생성, 업데이트 또는 삭제를 수행 할 때 제약 조건 위반이 없는지 여부와 치명적인 DB가 있는지 먼저 확인하기 때문에

2. 때로는 다른 곳에서 데이터를 가져와야하며, 구조가 얼마나 잘 구성되어 있는지 잘 모르기 때문에 FK를 삭제하기 만합니다.

삼. 여러 DB를 다루고 있고 다른 DB에 참조 키가있는 경우 FK를 제거 할 때까지 (데이터베이스 간 관계)
4. 또한 RDBMS에 관계없이 응용 프로그램을 작성하거나 RDBMS 시스템에서 DB를 내보내고 가져 오려는 경우도 있습니다.이 경우 각 특정 RDBMS 시스템에는 고유 한 FK 처리 방법이 있으며 아마도 FK 사용을 중단해야합니다.

5. RCMMS 플랫폼 (ORM)을 사용하는 경우 솔루션 및 기술에 따라 자체 맵핑을 제공하고 테이블 및 FK 작성에 신경 쓰지 않는다는 것을 알고 있습니다.

6. 마지막 요점은 FK가있는 DB를 다루는 지식과 FK가 필요하지 않은 모든 작업을 수행하는 응용 프로그램을 작성하는 지식이 될 것입니다. 장벽. 당신은 항상 당신이 얻을 수있는 최선의 최고를 실행하고 싶을 것입니다!


모두 감사합니다!

FK로 인해 문제가 발생할 수있는 경우는 키를 더 이상 사용할 수 없지만 조회 테이블에서 키를 참조하는 기록 데이터가있는 경우입니다.
분명히 해결책은 일을 더 잘 디자인하는 것이지만, 여기서 전체 솔루션을 항상 제어 할 수있는 것이 아닌 실제 상황을 생각하고 있습니다.
예 : 예를 들어 다양한 유형의 고객을 나열하는 조회 테이블 customer_type이 있습니다. 특정 고객 유형을 제거해야하지만 비즈니스 제약으로 인해 해당 고객을 제거 할 수 없다고 가정 해 보겠습니다. 클라이언트 소프트웨어를 업데이트하고 소프트웨어를 개발할 때 아무도이 상황을 발견하지 못했습니다. 다른 테이블의 외래 키라는 사실은 해당 데이터를 참조하는 히스토리 데이터를 알지 못하더라도 행을 제거하지 못하게 할 수 있습니다.
몇 번 화상을 입은 후에는 관계의 db 적용을 멀리 할 수 ​​있습니다.
(이것이 좋다고 말하는 것이 아닙니다. 일반적으로 FK와 db 제약 조건을 피하기로 결정한 이유를 알려주세요)

0
hamishmcn

내가 작업 한 프로젝트에서 많은 테이블이 같은 열에 조인 될 수 있도록 명시 적 관계가 아닌 암시 적 관계가 종종있었습니다.

다음 표를 참조하십시오

주소

  • 주소 ID (PK)
  • EntityId
  • EntityType
  • 시티
  • 상태
  • 국가
  • 기타..

EntityType의 가능한 값은 Employee, Company, Customer 일 수 있으며 EntityId는 관심있는 테이블의 primarky 키를 나타냅니다.

나는 이것이 이것이 최선의 방법이라고 생각하지 않지만이 프로젝트에서 효과가있었습니다.

0
Curtis

많은 것들과 마찬가지로, 그것은 절충입니다. 데이터 무결성을 확인하기 위해 어디에서 작업을 수행해야하는지에 대한 질문입니다.

(1) 외래 키를 사용하십시오 (테이블을 구성하는 단일 지점, 기능은 이미 구현, 테스트 및 작동하는 것으로 입증 됨)

(2) 데이터베이스 사용자에게 두십시오 (같은 테이블을 업데이트하는 여러 사용자/앱이 가능하여 잠재적 인 실패 지점이 많고 테스트가 복잡해집니다).

데이터베이스가 (2)보다 효율적이고 유지 관리가 쉬우 며 (1)의 위험이 줄어 듭니다.

0
Jen A

나는 Dmitriy가 말한 것을 반향하지만, 요점을 덧붙일 것입니다.

30+ 테이블에 큰 행 집합을 삽입해야하는 배치 청구 시스템에서 작업했습니다. 우리는 데이터 펌프 (Oracle)를 할 수 없었기 때문에 대량 삽입을해야했습니다. 이 테이블에는 외래 키가 있었지만 이미 관계가 깨지지 않았 음을 확인했습니다.

삽입 전에 외래 키 제약 조건을 비활성화하여 Oracle이 삽입을 영원히 수행하지 않도록합니다. 삽입이 성공하면 제약 조건을 다시 활성화합니다.

추신 : 단일 레코드에 대한 외래 키와 자식 행 데이터가 많은 대형 데이터베이스에서 외래 키가 잘못되어 계단식 삭제를 허용하지 않을 수 있습니다. 청구 시스템의 경우 계단식 삭제를 수행하면 데이터베이스에 너무 많은 시간과 비용이 소요되므로 기본 드라이버 (부모) 테이블의 필드에 레코드가 불량으로 표시됩니다.

0
typicalrunt

DB2에서 MQT (Materialized Query Tables)를 사용하는 경우 옵티마이 저가 지정된 쿼리에 적합한 계획을 선택하려면 외래 키 제한 조건이 필요합니다. 카디널리티 정보가 포함되어 있으므로 옵티마이 저는 메타 데이터를 많이 사용하여 MQT를 사용하거나 사용하지 않습니다.

0
Senthil

데이터 구조 설계의 좋은 원칙 중 하나는 테이블 또는 개체의 모든 특성에 대해 잘 이해 된 제약 조건이 적용되도록하는 것입니다. 사용자 나 프로그램이 데이터베이스의 유효한 데이터를 신뢰할 수있는 경우 나쁜 데이터로 인해 프로그램 결함이 발생할 가능성이 적으므로 중요합니다. 또한 오류 조건을 처리하기 위해 코드를 작성하는 데 더 적은 시간을 소비하며 오류 처리 코드를 미리 작성할 가능성이 높습니다.

대부분의 경우 이러한 제약 조건은 컴파일 타임에 정의 될 수 있으며,이 경우 속성이 항상 범위 내에 포함되도록 속성을 저장하거나 속성 저장 시도가 실패하도록 필터를 작성할 수 있습니다.

그러나 대부분의 경우 이러한 제약 조건은 런타임에 변경 될 수 있습니다. 예를 들어, "빨간색", "녹색"및 "파란색"의 값을 초기에받는 속성으로 "컬러"가있는 "자동차"테이블이있을 수 있습니다. 프로그램을 실행하는 동안 해당 초기 목록에 유효한 색상을 추가 할 수 있으며 추가 된 새로운 "자동차"는 최신 색상 목록의 모든 색상을 사용할 수 있습니다. 또한 일반적으로 프로그램을 다시 시작해도이 업데이트 된 색상 목록이 필요합니다.

귀하의 질문에 대답하기 위해 런타임에 변경 될 수있는 데이터 제약 조건이 필요하고 해당 변경 사항이 프로그램을 다시 시작한 후에도 외래 키가 문제에 대한 가장 간단하고 간결한 해결책이라는 것이 밝혀졌습니다. 개발 비용은 하나의 테이블 (예 : "컬러", "자동차"테이블에 대한 외래 키 제약 조건 및 인덱스)을 추가하는 것이며 런타임 비용은 최신 색상을위한 추가 테이블 조회입니다. 이 런타임 비용은 일반적으로 인덱싱 및 캐싱을 통해 완화됩니다.

이러한 요구 사항에 외래 키를 사용하지 않으면 목록을 관리하고 유효한 항목을보고 디스크에 저장하며 목록이 큰 경우 데이터를 효율적으로 구성하고 목록에 대한 업데이트가 없는지 확인하기 위해 소프트웨어를 작성해야합니다 여러 개의 리더 및/또는 라이터가있는 경우 목록 파일을 손상시키고 목록에 대한 직렬 액세스를 제공하십시오. 즉, 많은 RDBMS 기능을 구현해야합니다.

0
Jay Godse

나는 항상 그것들을 사용하지 않는 것이 게으르다 고 생각했다. 나는 항상 이루어져야한다는 것을 배웠다. 그러나 나는 Joel의 이야기를 듣지 않았습니다. 그는 그럴만한 이유가 있었을 지 모르겠다.

0
Kilhoffer

Q uite 종종 FK constraints 하위 행을 추가하거나 업데이트 할 수 없습니다 : 외래 키 제약 조건 실패 두 개의 테이블 inventory_source와 contract_lines가 있다고 가정합니다. inventory_source_id in contract_lines in inventory_source 참조하고 우리가 inventory_source에서 레코드를 삭제하려고하고 레코드가 이미 contract_lines에 있거나 기본 테이블에서 PK 열을 삭제하려고하면 FK 제약 조건에 대한 오류가 발생합니다. 아래에 적힌 단계를 사용하여 피할 수 있습니다.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

다음 단계를 사용하여 극복 할 수 있습니다.

  1. Inventory_source에서 행을 삭제하거나 업데이트하면 contract_lines 테이블에서 일치하는 행을 자동으로 삭제하거나 업데이트하며이를 계단식 삭제 또는 업데이트라고합니다.
  2. 이를 수행하는 또 다른 방법은 contract_lines 테이블의 열 (즉, contract_lines 테이블의 해당 항목에 대한 레코드가 inventory_source 테이블에서 삭제 된 경우)을 NULL로 설정하는 것입니다.
  3. 부모 테이블을 삭제 또는 업데이트로 제한 할 수 있습니다. 즉, inventory_source 테이블에 대한 삭제 또는 업데이트 조작을 거부 할 수 있습니다.
  4. 참조 된 테이블에 관련 외래 키 값이 있으면 기본 키 값을 삭제하거나 업데이트 할 수 없습니다.
0
Vikas Kukreti