외국 열쇠가 왜 이래요?
저는 조엘 스폴스키가 팟캐스트 014에서 외국 키를 거의 사용하지 않았다고 언급한 것을 기억합니다(제 기억이 맞다면).하지만 데이터베이스 전체에서 중복 및 그에 따른 데이터 무결성 문제를 방지하는 데 매우 중요해 보입니다.
(스택 오버플로 원칙에 따른 토론을 피하기 위해) 그 이유에 대해 사람들이 확실한 이유를 가지고 있습니까?
"저는 아직 외국 키를 만들 이유가 없기 때문에, 이것이 실제로 키를 설정하는 첫 번째 이유일지도 모릅니다.
외부 키를 사용하는 이유:
- 고아 행을 얻지 못할 것입니다.
- 자동으로 테이블을 정리하는 "캐스케이드 삭제 시" 동작을 잘 얻을 수 있습니다.
- Optimizer는 데이터베이스의 테이블 간의 관계에 대해 알고 있으면 가입 카디널리티에 대한 더 나은 추정치를 얻을 수 있으므로 쿼리를 가장 효율적으로 실행할 수 있도록 계획하는 데 도움이 됩니다.
- FK는 데이터베이스에서 어떤 통계를 수집하는 것이 가장 중요한지에 대해 상당히 큰 힌트를 주고, 이는 결과적으로 더 나은 성능으로 이어집니다.
- ORM이 직접 생성할 수 있고 시각화 도구가 사용자를 위해 멋진 스키마 레이아웃을 만들 수 있는 등 모든 종류의 자동 생성 지원이 가능합니다.
- 그렇지 않으면 암묵적인 관계가 명시적으로 문서화되기 때문에 프로젝트에 처음 참여하는 사람은 사물의 흐름에 더 빨리 참여할 것입니다.
외부 키를 사용하지 않는 이유:
- 당신은 FK 일관성을 확인해야 하기 때문에 모든 CRUD 작업에서 DB를 추가로 작업하도록 하고 있습니다.만약 당신이 이탈을 많이 한다면 이것은 큰 비용이 될 수 있습니다.
- 관계를 강화함으로써, FK는 사용자가 추가/삭제해야 하는 순서를 지정하고, 이로 인해 DB는 사용자가 원하는 작업을 수행하는 것을 거부할 수 있습니다(물론, 이러한 경우에는 사용자가 하려는 작업은 고아 행(Orianed Row)을 만드는 것이며, 일반적으로 좋은 작업이 아닙니다).특히 대용량 배치 업데이트를 수행할 때 한 테이블을 먼저 로드하고 두 번째 테이블이 일관된 상태를 생성하는 경우(하지만 두 번째 로드가 실패하여 데이터베이스가 일관되지 않을 가능성이 있는 경우에는 이와 같은 작업을 수행해야 합니까?).
- 때때로 당신은 당신의 데이터가 더럽게 될 것이라는 것을 미리 알고, 당신은 그것을 받아들이고, 당신은 DB가 그것을 받아들이기를 원합니다.
- 그냥 게으른거에요 :-)
대부분의 확립된 데이터베이스는 강제되지 않고 단순히 약간의 메타데이터일 뿐인 외부 키를 지정할 수 있는 방법을 제공한다고 생각합니다.FK를 사용하지 않는 이유는 비강행으로 모두 없애므로, 두 번째 섹션에 있는 이유 중 하나라도 적용된다면 아마 그 길로 가야 할 것입니다.
이것은 양육에 관한 문제입니다.만약 여러분이 교육적 혹은 전문적인 직업 어딘가에서 데이터베이스를 공급하고 돌보는데 시간을 보냈다면(또는 그렇게 한 재능 있는 사람들과 긴밀하게 협력했다면), 여러분의 사고 과정에는 실체와 관계의 기본적인 원칙이 잘 자리잡고 있을 것입니다.이러한 기본값 중에는 데이터베이스에 키를 지정하는 방법/시기/이유(기본, 외부 및 대체)가 있습니다.제2의 자연입니다.
그러나 RDBMS와 관련된 노력을 충분히 또는 긍정적으로 경험한 적이 없다면, 그러한 정보에 노출되지 않았을 가능성이 높습니다.또는 과거에는 데이터베이스를 반대하는 목소리가 높던 환경에 몰입한 경우도 있을 수 있습니다(예: "DBA는 바보입니다. 우리는 거의 선택하지 않았습니다. java/c# 코드 슬링어를 거의 선택하지 않았습니다.").이 경우에 당신은 FK(그리고 그들이 암시할 수 있는 제약)가 정말로 중요하다고 말하는 일부 바보들의 기막힌 옹알이에 격렬하게 반대할 수도 있습니다.
대부분의 사람들은 어렸을 때 양치질이 중요하다고 배웠습니다.당신은 그것 없이 버틸 수 있습니까?물론이죠, 하지만 식후에 양치질을 했다면 사용할 수 있는 치아 수보다 적어질 거예요.만약 엄마와 아빠가 구강위생뿐만 아니라 데이터베이스 디자인까지 책임감 있게 다룬다면 우리는 이런 대화를 하지 않을 것입니다. :-)
당신이 그것을 피할 수 있는 많은 애플리케이션들이 있을 것이라고 확신하지만, 그것은 최선의 아이디어가 아닙니다.데이터베이스를 제대로 관리하기 위해 항상 애플리케이션에 의존할 수는 없으며, 솔직히 데이터베이스를 관리하는 것이 애플리케이션에 큰 관심사는 아닐 것입니다.
관계형 데이터베이스를 사용하는 경우 관계형 데이터베이스에 정의된 관계가 있어야 합니다.불행히도 이러한 태도(외산 키가 필요 없음)는 데이터 무결성과 같은 어리석은 일에 신경 쓰지 않으려는 많은 애플리케이션 개발자들에게 받아들여지고 있는 것으로 보입니다(그러나 자사에는 전용 데이터베이스 개발자가 없기 때문에 그렇게 해야 합니다).일반적으로 데이터베이스에서는 기본 키만 있으면 운이 좋습니다;)
외부 키는 관계형 데이터베이스 모델에 필수적입니다.
나는 항상 그것들을 사용하지만, 그 다음에는 금융 시스템을 위한 데이터베이스를 만듭니다.데이터베이스는 응용프로그램의 중요한 부분입니다.재무 데이터베이스의 데이터가 완전히 정확하지 않다면 코드/프론트 엔드 설계에 얼마나 많은 노력을 기울이는지는 중요하지 않습니다.당신은 시간을 낭비하고 있을 뿐입니다.
또한 여러 시스템이 일반적으로 데이터베이스와 직접 인터페이스해야 한다는 사실도 있습니다. 데이터를 방금 읽은 다른 시스템(Crystal Reports)부터 데이터를 삽입하는 시스템(꼭 제가 설계한 API를 사용하지는 않음)까지. VBScript를 막 발견하고 SQL에 대한 SA 암호를 가진 우둔한 관리자가 작성할 수도 있습니다.박스).데이터베이스가 바보 같은 짓을 하지 않는다면, 안녕 데이터베이스입니다.
데이터가 중요한 경우, 예, 외부 키를 사용하여 데이터와 상호 작용할 수 있는 저장 프로시저 모음을 만들고 최대한 강력한 DB를 만듭니다.데이터가 중요하지 않다면 왜 처음부터 데이터베이스를 만들고 있습니까?
업데이트: 나는 지금 항상 외국키를 사용합니다."그들은 복잡한 테스트"라는 반대 의견에 대한 제 대답은 "그들이 데이터베이스를 전혀 필요로 하지 않도록 당신의 단위 테스트를 작성하라"는 것입니다.데이터베이스를 사용하는 모든 테스트는 데이터베이스를 적절하게 사용해야 하며 여기에는 외부 키가 포함됩니다.설정이 고통스럽다면 덜 고통스러운 방법을 찾으세요."
자동화된 테스트를 복잡하게 만드는 외국어 키
당신이 외국 열쇠를 사용한다고 가정해 보겠습니다.당신은 "금융 계좌를 업데이트할 때 거래 기록을 저장해야 한다"는 자동화된 테스트를 작성하고 있습니다.이 검정에서는 두 개의 표에만 관심을 가집니다.accounts
그리고.transactions
.
,accounts
외국 열쇠를 가지고 있습니다.contracts
,그리고.contracts
는에 대한 .clients
,그리고.clients
는에 대한 .cities
,그리고.cities
는에 대한 .states
.
이제 데이터베이스에서는 테스트와 관련이 없는 4개의 테이블에 데이터를 설정하지 않고 테스트를 실행할 수 없습니다.
이에 대한 최소한 두 가지 가능한 관점이 있습니다.
- "그것은 좋은 일입니다. 테스트가 현실적이어야 하며, 이러한 데이터 제약은 생산 과정에서 존재할 것입니다."
- "그것은 나쁜 일입니다. 다른 부분을 포함하지 않고 시스템의 테스트 부분을 통합할 수 있어야 합니다.시스템 전체에 대한 통합 테스트를 추가할 수 있습니다."
테스트를 실행하는 동안 일시적으로 외부 키 검사를 끌 수도 있습니다.적어도 MySQL은 이를 지원합니다.
"이들은 레코드를 삭제하는 것을 더 번거롭게 만들 수 있습니다. 외국 키가 그러한 제약 조건을 위반할 수 있는 다른 테이블에 레코드가 있는 경우 "마스터" 레코드를 삭제할 수 없습니다.
SQL 표준은 외부 키가 삭제되거나 업데이트될 때 수행되는 작업을 정의한다는 점을 기억해야 합니다.제가 아는 것은 다음과 같습니다.
ON DELETE RESTRICT
- 이 열의 키가 있는 다른 테이블의 행을 삭제할 수 없습니다.이것은 켄 레이가 위에서 설명한 것입니다.ON DELETE CASCADE
- 다른 테이블의 행이 삭제된 경우 이 테이블의 행을 참조하는 행을 삭제합니다.ON DELETE SET DEFAULT
- 다른 테이블의 행이 삭제된 경우, 해당 행을 참조하는 외부 키를 해당 열의 기본값으로 설정합니다.ON DELETE SET NULL
- 다른 테이블의 행이 삭제된 경우 이 테이블의 행을 참조하는 외부 키를 null로 설정합니다.ON DELETE NO ACTION
- 이 외래 키는 외래 키임을 표시할 뿐입니다. 즉, OR 맵퍼에 사용하기 위한 것입니다.
이와 같은 조치는 다음의 경우에도 적용됩니다.ON UPDATE
.
기본값은 사용하는 sql 서버에 따라 달라지는 것 같습니다.
@impassing - 이것이 바로 유지보수 악몽을 야기하는 사고방식입니다.
데이터가 최소한 일관성을 보장할 수 있는 선언적 참조 무결성을 무시하고 기껏해야 약한 예방 조치인 소위 "소프트웨어 시행"을 선호하는 이유는 무엇입니까?
그것들을 사용하지 않는 한 가지 좋은 이유가 있습니다.만약 당신이 그들의 역할이나 사용법을 이해하지 못한다면.
잘못된 상황에서 외국 키 제약은 사고의 폭포 복제로 이어질 수 있습니다.만약 누군가 잘못된 기록을 제거한다면, 그것을 되돌리는 것은 엄청난 일이 될 수 있습니다.
또한, 반대로 무언가를 제거해야 할 때, 잘못 설계된 경우 제약으로 인해 모든 종류의 잠금이 발생할 수 있습니다.
그것들을 사용하지 않을 정당한 이유가 없습니다.고아가 된 사람들이 당신에게 별 문제가 아닌 이상 말입니다.
"레코드를 추가하기 전에 해당 레코드가 다른 테이블에 존재하는지 확인하십시오."는 비즈니스 논리입니다.
데이터베이스에 이 작업을 원하지 않는 몇 가지 이유는 다음과 같습니다.
업무 규칙이 변경되면 데이터베이스를 변경해야 합니다.데이터베이스는 많은 경우 인덱스를 다시 만들어야 하며, 이는 큰 테이블에서는 느립니다.(변경 규칙은 다음과 같습니다. 게스트가 메시지를 게시하거나 댓글을 달았음에도 불구하고 계정을 삭제할 수 있습니다.)
데이터베이스를 변경하는 것은 운영 저장소에 변경 사항을 푸시하여 소프트웨어 수정 사항을 배포하는 것만큼 쉽지 않습니다.우리는 가능한 한 데이터베이스 구조를 변경하는 것을 피하고 싶습니다.데이터베이스에 비즈니스 로직이 많을수록 데이터베이스를 변경해야 할 가능성이 높아지며 재인덱스가 트리거됩니다.
TDD. 단위 테스트에서 데이터베이스를 모의실험으로 대체하고 기능을 테스트할 수 있습니다.데이터베이스에 비즈니스 로직이 있는 경우 완벽한 테스트를 수행하지 않으며, 테스트 목적으로 데이터베이스와 함께 테스트하거나 코드로 비즈니스 로직을 복제해야 하므로 로직이 중복되고 로직이 동일한 방식으로 작동하지 않을 가능성이 높아집니다.
논리를 다른 데이터 소스에 재사용합니다.데이터베이스에 로직이 없는 경우, 애플리케이션은 데이터베이스의 레코드에서 개체를 생성하거나 웹 서비스, json 파일 또는 기타 소스에서 개체를 생성할 수 있습니다.저는 데이터 맵퍼 구현을 교체하기만 하면 되고 모든 소스와 비즈니스 로직을 사용할 수 있습니다.데이터베이스에 논리가 있는 경우에는 불가능하며 데이터 맵퍼 계층이나 비즈니스 논리에 논리를 구현해야 합니다.어느 쪽이든 간에, 당신은 당신의 코드에 그 체크가 필요합니다.데이터베이스에 논리가 없으면 다른 데이터베이스 또는 플랫 파일 구현을 사용하여 다른 위치에 애플리케이션을 배포할 수 있습니다.
제 경험으로는 데이터베이스 크리티컬 애플리케이션에서 FK를 사용하지 않는 것이 좋습니다.저는 FK가 좋은 관행이지만 데이터베이스가 방대하고 초당 CRUD 작업이 방대한 곳에서는 실용적이지 않다는 사람들의 의견에 동의하지 않을 것입니다.이름을 지정하지 않고 공유할 수 있습니다...가장 큰 투자 은행 중 하나는 데이터베이스에 단 하나의 FK도 가지고 있지 않습니다.이러한 제약은 DB와 관련된 응용프로그램을 작성하는 동안 프로그래머가 처리합니다.기본적인 이유는 새로운 CRUD를 실행할 때마다 여러 개의 테이블을 적용하고 각 삽입/업데이트를 확인해야 하기 때문입니다. 단 하나의 행에 영향을 미치는 쿼리의 경우 큰 문제가 되지 않지만 배치 처리를 처리할 때 큰 지연 시간이 발생하기 때문입니다.
FK를 피하는 것이 더 좋지만, FK의 위험은 프로그래머가 처리해야 합니다.
더 큰 질문은 눈가리개를 하고 운전을 하겠습니까?참조 제약이 없는 시스템을 개발하면 그렇게 됩니다.비즈니스 요구사항이 변경되고, 애플리케이션 설계가 변경되며, 코드 변경 시 각각의 논리적 가정이 변경되고, 논리 자체가 재분류될 수 있다는 점을 명심해야 합니다.일반적으로 데이터베이스의 제약은 현대의 논리적 가정 하에서 이루어지며, 특정한 논리적 주장 및 가정에 대해 올바른 것으로 보입니다.
애플리케이션의 라이프사이클을 통해 참조 및 데이터 검사는 특히 새로운 요구사항이 논리적 애플리케이션을 변화시킬 때 애플리케이션을 통한 데이터 수집을 제한합니다.
이 목록의 주제에 대해 말하자면, 외국어 키는 그 자체로 "성능을 향상"시키지도 않고, 실시간 거래 처리 시스템의 관점에서 "성능을" 크게 저하시키지도 않습니다.그러나 HIGH volume "batch" 시스템에서 제약 조건 점검을 위한 총 비용이 발생합니다.다음은 실시간 대 배치 트랜잭션 프로세스의 차이입니다. 배치 처리 - 제약 조건 검사를 통해 발생한 총 비용이 성능에 영향을 미치는 경우입니다.
잘 설계된 시스템에서 데이터 일관성 검사는 배치를 처리하기 전에 "전"에 수행됩니다(비록 여기에 관련된 비용이 있음에도 불구하고). 따라서 로드 시간 동안에는 외부 키 제약 조건 검사가 필요하지 않습니다.실제로 배치가 처리될 때까지 외부 키를 포함한 모든 제약 조건을 일시적으로 비활성화해야 합니다.
QUREE PERFORMANCE - 테이블이 외부 키에 결합되어 있는 경우, 외부 키 열이 NOT INDEXED되지 않는다는 사실을 인지해야 합니다(각 기본 키는 정의에 따라 인덱싱됨).외부 키를 색인화하고, 색인화된 테이블에 결합하면 외부 키 제약 조건이 있는 색인화되지 않은 키에 결합하는 것이 아니라 성능 향상에 도움이 됩니다.
제목을 변경하는 경우, 데이터베이스가 웹 사이트 표시/내용 렌더링/클릭 기록만 지원하는 경우, 모든 테이블에 모든 제약 조건이 있는 데이터베이스는 이러한 목적으로 오버킬됩니다.생각해 보세요.대부분의 웹사이트는 데이터베이스를 사용하지 않습니다.데이터가 기록 중이고 참조되지 않는 경우와 유사한 요구 사항의 경우 제약 조건이 없는 인메모리 데이터베이스를 사용합니다.이것은 데이터 모델이 없다는 것을 의미하지는 않습니다. 예, 논리적 모델이 있지만 물리적 데이터 모델이 없다는 것을 의미합니다.
데이터 일관성을 유지하는 데 유용하다는 점에서 이전 답변에 동의합니다.그러나 몇 주 전 제프 애트우드가 정규화되고 일관된 데이터의 장단점에 대해 논의한 흥미로운 게시물이 있었습니다.
다시 말해, 방대한 양의 데이터를 처리할 때 정규화되지 않은 데이터베이스가 더 빨라질 수 있습니다. 애플리케이션에 따라 정확한 일관성에 신경 쓰지 않을 수도 있지만, DB가 그렇지 않기 때문에 데이터를 처리할 때 훨씬 더 신중해야 합니다.
Clarify 데이터베이스는 기본 키나 외부 키가 없는 상용 데이터베이스의 한 예입니다.
http://www.geekinterview.com/question_details/18869
재미있는 것은, 기술 문서가 테이블이 어떻게 연관되어 있는지, 테이블을 결합하기 위해 어떤 열을 사용해야 하는지 등을 설명하는 데 긴 시간이 걸린다는 것입니다.
다시 말해, 그들은 명시적 선언(DRI)으로 테이블에 합류할 수 있었지만, 그렇지 않기로 선택했습니다.
따라서 Clarify 데이터베이스는 불일치로 가득 차 있으며 성능이 떨어집니다.
하지만 삭제하기 전에 관련된 행을 확인하는 등의 참조 무결성을 처리하기 위해 코드를 작성할 필요 없이 개발자들의 작업을 쉽게 해주었다고 생각합니다.
그리고 그것이 관계형 데이터베이스에 외국 키 제약이 없는 주된 이점이라고 생각합니다.이를 통해 개발이 더 쉬워집니다. 적어도 이는 악마적인 관리 관점에서는 가능합니다.
만약 당신이 미래에 하나의 기본 데이터베이스 시스템이 변하지 않을 것이라고 확신한다면, 저는 데이터 무결성을 보장하기 위해 외국 키를 사용할 것입니다.
하지만 여기에 외국 열쇠를 전혀 사용하지 않는 또 하나의 아주 좋은 현실적인 이유가 있습니다.
다른 데이터베이스 시스템을 지원해야 하는 제품을 개발 중입니다.
다양한 데이터베이스 시스템에 연결할 수 있는 엔티티 프레임워크를 사용하는 경우 "오픈 소스 무료" 서버리스 데이터베이스도 지원할 수 있습니다.일부 데이터베이스가 외부 키 규칙(업데이트, 행 삭제...)을 지원하지 않을 수도 있습니다.
이로 인해 다음과 같은 여러 가지 문제가 발생할 수 있습니다.
1.) 데이터베이스 구조를 만들거나 업데이트할 때 오류가 발생할 수 있습니다.데이터베이스 시스템에서 외부 키를 무시하기 때문에 자동 오류만 발생할 수도 있습니다.
2.) 만약 당신이 외국 키에 의존한다면, 당신은 당신의 비즈니스 로직에서 데이터 무결성 검사를 덜 하거나 아예 하지 않을 것입니다.이제 새 데이터베이스 시스템이 이러한 외래 키 규칙을 지원하지 않거나 다른 방식으로 동작할 경우 비즈니스 논리를 다시 작성해야 합니다.
질문할 수 있습니다.누가 다른 데이터베이스 시스템을 필요로 합니까?모든 사람이 자신의 컴퓨터에 SQL-Server를 설치할 여유가 있거나 원하는 것은 아닙니다.이것은 소프트웨어이며, 유지 관리가 필요합니다.다른 사람들은 이미 다른 DB 시스템에 시간과 돈을 투자했습니다.서버리스 데이터베이스는 하나의 컴퓨터에 있는 소규모 고객들에게 매우 적합합니다.
이 모든 DB 시스템이 어떻게 작동하는지는 아무도 알 수 없지만 무결성 검사를 통해 비즈니스 논리는 항상 그대로 유지됩니다.
이렇게 하면 레코드 삭제가 더 번거로워질 수 있습니다. 다른 테이블에 외국 키가 해당 제약 조건을 위반하는 레코드가 있는 경우 "마스터" 레코드를 삭제할 수 없습니다.트리거를 사용하여 계단식 삭제를 수행할 수 있습니다.
기본 키를 현명하지 않게 선택한 경우 해당 값을 변경하는 것은 훨씬 더 복잡해집니다.예를 들어, 내 "고객" 테이블의 PK를 그 사람의 이름으로 가지고 있고, 그 키를 "주문" 테이블의 FK로 만든다면, 고객이 이름을 바꾸고 싶다면, 그것은 왕실의 고통입니다.하지만 그것은 단지 조잡한 데이터베이스 설계일 뿐입니다.
나는 파이어사인 키를 사용하는 것의 장점이 예상되는 단점보다 더 많다고 생각합니다.
외부 키 제약 조건을 확인하는 데는 CPU 시간이 다소 걸리므로 일부 사용자는 추가 성능을 얻기 위해 외부 키를 생략합니다.
외국인 키를 사용해야 하는 추가 이유: - 데이터베이스를 더 많이 재사용할 수 있습니다.
외래 키를 사용하지 않는 추가 이유: - 재사용을 줄임으로써 고객을 도구에 고정하려고 합니다.
오라클 데이터베이스만 알고 있고 다른 데이터베이스는 알고 있지 않으며, 데이터 무결성을 유지하는 데 외국인 키가 필수적임을 알 수 있습니다.데이터를 삽입하기 전에 데이터 구조를 만들고 올바르게 만들어야 합니다.이 작업이 완료되면 모든 기본 키와 외부 키가 생성됩니다. 작업이 완료됩니다!
고아가 된 줄은? 아니, 난생 처음 봐요서투른 프로그래머가 외국 키를 잊어버리거나, 다른 차원에서 구현한 것이 아니라면 말입니다.두 가지 모두 오라클의 맥락에서 볼 때 데이터 중복, 고아 데이터 등으로 이어지는 큰 실수입니다. 즉, 데이터 손상입니다.FK가 적용되지 않는 데이터베이스는 상상할 수 없습니다.제가 보기엔 혼란스러운데요.이것은 유닉스 퍼미션 시스템과 약간 비슷합니다. 모든 사람이 뿌리라고 상상해보세요.혼란을 생각해 보세요.
기본 키와 마찬가지로 외부 키도 필수입니다.기본 키를 제거하면 어떨까요? 완전한 혼란이 일어날 겁니다.그게 바로 그거.기본 또는 외부 키 책임을 프로그래밍 수준으로 이동할 수 없으며, 데이터 수준이어야 합니다.
단점?네, 물론이죠! 삽입하면 더 많은 체크가 발생하기 때문입니다.하지만 데이터 무결성이 성능보다 더 중요하다면 쉽게 해결할 수 있습니다.Oracle의 성능 문제는 PK 및 FK와 함께 제공되는 인덱스와 더 관련이 있습니다.
제가 들은 바로는 프론트 엔드에 이러한 비즈니스 규칙이 있어야 한다는 것입니다.외래 키는 처음부터 제약 조건을 깨는 삽입을 허용해서는 안 될 때 "불필요한 오버헤드를 추가"합니다.저도 동의하나요?아니요, 하지만 제가 항상 듣던 말입니다.
편집: 제 생각에 그는 외국 키의 개념이 아니라 외국 키의 제약을 언급한 것 같습니다.
저는 ACID 표준에 따라 진행하고 싶다면 참조 무결성을 보장하기 위해 외국 키를 보유하는 것이 중요합니다.
여기 댓글 대부분을 두 번째로 달아야 합니다. 외국어 키는 데이터가 무결성이 있는지 확인하는 데 필요한 항목입니다.ON DELETE과 ON UPDATE의 다른 옵션을 사용하면 사용과 관련하여 사람들이 언급하는 "다운 폴(down fall)"의 일부를 피할 수 있습니다.
저는 모든 프로젝트의 99%에서 데이터의 무결성을 강화하기 위해 FK를 사용하게 될 것임을 알고 있습니다. 하지만 고객이 이전 데이터를 보관해야 하는 경우는 매우 드물기도 합니다.하지만 어쨌든 유효한 데이터를 얻기 위해 많은 시간을 코드를 작성하기 때문에 무의미해집니다.
애플리케이션 수명 주기 전반에 걸쳐 유지보수성과 일관성은 어떻습니까?대부분의 데이터는 이를 활용하는 애플리케이션보다 수명이 더 깁니다.관계와 데이터 무결성은 다음 개발자 팀이 앱 코드에서 올바르게 이해할 수 있기를 바라기에는 너무 중요합니다.자연스러운 관계를 존중하지 않는 더러운 데이터를 가진 db 작업을 해보지 않았다면 그렇게 될 것입니다.그러면 데이터 무결성의 중요성이 매우 분명해질 것입니다.
또한 대부분의 데이터베이스에서 외국 키는 필수라고 생각합니다.유일한 단점(일관성 강화에 따른 성능 히트 외에도)은 외부 키를 사용하면 사용자가 기능하는 외부 키가 있다고 가정하는 코드를 작성할 수 있다는 것입니다.그것은 절대로 허용되어서는 안됩니다.
예를 들어, 참조 테이블에 삽입한 후 첫 번째 삽입이 성공했는지 확인하지 않고 참조 테이블에 삽입을 시도하는 코드를 작성하는 사람들을 본 적이 있습니다.나중에 외부 키가 제거되면 데이터베이스가 일관되지 않습니다.
업데이트 또는 삭제 시 특정 동작을 가정할 수 있는 옵션도 없습니다.외국 키가 있는지 여부와 상관없이 원하는 작업을 수행하려면 여전히 코드를 작성해야 합니다.삭제가 계단식이 아닌 경우에 삭제가 계단식이라고 가정하면 삭제가 실패합니다.참조된 열에 대한 업데이트가 참조된 행에 전달되지 않는다고 가정하면 업데이트가 실패합니다.코드를 작성하기 위해서는 그런 기능이 없을 수도 있습니다.
이러한 기능이 켜져 있으면 코드가 이러한 기능을 에뮬레이트하게 되고 성능이 약간 저하됩니다.
그래서, 요약하면..일관성 있는 데이터베이스가 필요한 경우 외국인 키가 필수적입니다.외부 키가 사용자가 작성한 코드에 존재하거나 작동하는 것으로 가정해서는 안 됩니다.
나는 드미트리의 대답을 반복합니다 - 아주 잘 표현했습니다.
FK가 자주 가져오는 성능 오버헤드에 대해 걱정하는 사람들을 위해 삽입, 삭제 또는 업데이트 시 제약 조건 검증에 따른 비용 오버헤드 없이 FK 제약 조건의 쿼리 최적화 장점을 얻을 수 있는 방법이 있습니다.즉, RELY DISELE NOVALIDATE 속성을 사용하여 FK 제약 조건을 만듭니다.즉, 쿼리 최적화자는 데이터베이스가 실제로 제약 조건을 적용하지 않고 쿼리를 작성할 때 제약 조건이 적용되었다고 가정합니다.이와 같이 FK 제약 조건이 있는 테이블을 채울 때는 FK 열에 제약 조건을 위반하는 데이터가 없는지 확인하기 위해 매우 주의해야 합니다. 마치 이 FK 제약 조건이 있는 테이블과 관련된 쿼리에서 신뢰할 수 없는 결과를 얻을 수 있는 것처럼 말입니다.
저는 보통 데이터 마트 스키마의 일부 테이블에서는 이 전략을 사용하지만 통합 스테이징 스키마에서는 사용하지 않습니다.데이터를 복사하는 테이블에 이미 동일한 제약 조건이 적용되었는지, 아니면 ETL 루틴이 제약 조건을 적용하는지 확인합니다.
여기서 답변하는 많은 사람들은 참조 제약을 통해 구현되는 참조 무결성의 중요성에 너무 집착합니다.참조 무결성이 있는 대규모 데이터베이스에서 작업하는 것은 성능이 좋지 않습니다.Oracle은 계단식 삭제에 특히 서투른 것으로 보입니다.제 경험의 법칙은 애플리케이션이 데이터베이스를 직접 업데이트해서는 안 되며 저장 프로시저를 거쳐야 한다는 것입니다.이렇게 하면 데이터베이스 내부에 코드베이스가 유지되며, 데이터베이스가 무결성을 유지합니다.
많은 응용프로그램이 데이터베이스에 액세스하는 경우 참조 무결성 제약으로 인해 문제가 발생하지만 이는 제어의 문제입니다.
애플리케이션 개발자들은 데이터베이스 개발자들이 반드시 익숙지 않을 수도 있는 매우 다른 요구사항들을 가지고 있을 수 있다는 점에서 더 큰 문제가 있습니다.
외국 키에 인덱스를 입력하는 것을 잊어버리고 특정 작업이 느리다고 불평한 사람들로부터(제약 조건 확인이 어떤 인덱스의 이점을 활용할 수 있기 때문에) 저도 이 주장을 들은 적이 있습니다.요약하자면:외국 열쇠를 사용하지 않을 이유가 없습니다.모든 최신 데이터베이스는 계단식 삭제를 지원하기 때문에...
FK로 인해 문제가 발생할 수 있는 경우는 더 이상 키를 사용할 수 없게 되었더라도 (룩업 테이블에서) 키를 참조하는 기록 데이터가 있을 때입니다.
분명히 해결책은 일을 더 잘 설계하는 것입니다. 하지만 저는 여러분이 항상 완전한 해결책을 통제할 수 있는 것이 아닌 현실 세계의 상황을 생각하고 있습니다.
예를 들어, 조회 테이블이 있을 수 있습니다.customer_type
고객 수 할 때 도 이 하지 않았습니다.합니다. 예를 들어 특정 고객 유형을 제거해야 하지만 (업무상 제약으로) 클라이언트 소프트웨어를 업데이트할 수 없으며 소프트웨어를 개발할 때 아무도 이 상황을 고려하지 않았습니다.일부 다른 표에서 외래 키라는 사실은 참조하는 과거 데이터가 무관하다는 것을 알더라도 행을 제거하는 것을 방해할 수 있습니다.
이로 인해 몇 번 화상을 입은 후에는 아마도 관계의 DB 적용을 피하게 될 것입니다.
(이것이 좋다고 말하는 것이 아니라 일반적으로 FK와 db 제약을 피하기로 결정할 수 있는 이유를 말하는 것입니다.)
드미트리가 한 말을 그대로 따라하겠지만, 한 가지만 덧붙이면 됩니다.
저는 30개 이상의 테이블에 큰 행 집합을 삽입해야 하는 일괄 청구 시스템을 작업했습니다.데이터 펌프(Oracle)를 할 수 없어서 대량 삽입을 해야 했습니다.그 테이블에는 외국 열쇠가 놓여 있었지만, 우리는 그들이 어떤 관계도 깨지지 않는다는 것을 이미 확인했습니다.
삽입하기 전에 외부 키 제약 조건을 비활성화하여 Oracle이 삽입을 수행하는 데 시간이 오래 걸리지 않도록 합니다.삽입이 성공한 후 제약 조건을 다시 활성화합니다.
PS: 단일 레코드에 대해 많은 외부 키와 하위 행 데이터가 있는 대규모 데이터베이스에서는 외부 키가 잘못될 수 있으므로 계단식 삭제를 허용하지 않을 수 있습니다.청구 시스템에 있는 당사의 경우 삭제를 단계적으로 수행할 경우 시간이 너무 오래 걸리고 데이터베이스에 부담이 되기 때문에 메인 드라이버(부모) 테이블에 필드가 있는 경우 기록이 나쁘다고 표시할 뿐입니다.
언급URL : https://stackoverflow.com/questions/83147/whats-wrong-with-foreign-keys
'programing' 카테고리의 다른 글
간단한 Oracle 변수 SQL 할당 (0) | 2023.10.22 |
---|---|
ajax를 사용하여 로드 데이터 2개를 선택하면 옵션을 선택할 수 없습니다. (0) | 2023.10.22 |
DataTable을 직렬화할 수 없습니다.DataTable 이름이 설정되지 않았습니다. (0) | 2023.10.22 |
윈도우즈에서 서명되지 않은 __int64의 printf 형식 (0) | 2023.10.22 |
WordPress 내에 응답 테이블을 만듭니다. (0) | 2023.10.22 |