내가 아는 한, 외래 키 (FK)는 프로그래머가 올바른 방식으로 데이터를 조작하도록 돕는 데 사용됩니다. 프로그래머가 실제로이 작업을 이미 올바른 방식으로 수행하고 있다고 가정하면 외래 키 개념이 정말로 필요합니까?
외래 키에 대한 다른 용도가 있습니까? 여기에 뭔가 빠졌나요?
내가 아는 한, 외래 키 (FK)는 프로그래머가 올바른 방식으로 데이터를 조작하도록 돕는 데 사용됩니다. 프로그래머가 실제로이 작업을 이미 올바른 방식으로 수행하고 있다고 가정하면 외래 키 개념이 정말로 필요합니까?
외래 키에 대한 다른 용도가 있습니까? 여기에 뭔가 빠졌나요?
답변:
외래 키는 데이터 수준에서 참조 무결성을 적용하는 데 도움이됩니다. 또한 일반적으로 기본적으로 색인이 생성되기 때문에 성능도 향상됩니다.
외래 키는 프로그래머가 ON DELETE CASCADE
. 즉, 사용자를 포함하는 하나의 테이블과 주문 등을 포함하는 다른 테이블이있는 경우 사용자를 삭제하면 해당 사용자를 가리키는 모든 주문이 자동으로 삭제 될 수 있습니다.
외래 키없이 데이터베이스를 디자인하는 것은 상상할 수 없습니다. 그것들이 없으면 결국 실수를하고 데이터의 무결성을 손상시킬 수밖에 없습니다.
엄격히 말하면 필수 는 아니지만 이점은 엄청납니다.
나는 FogBugz 가 데이터베이스에 외래 키 제약 조건을 가지고 있지 않다고 확신 합니다. 나는 Fog Creek Software 팀이 불일치가 발생하지 않도록 코드를 구조화 하는 방법을 듣고 싶습니다 .
예.
ON DELETE CASCADE
프로그래머가 실제로이 작업을 이미 올바른 방식으로 수행하고 있다고 가정합니다.
그런 가정을하는 것은 매우 나쁜 생각 인 것 같습니다. 일반적으로 소프트웨어는 엄청나게 버그가 많습니다.
그리고 그것이 정말로 요점입니다. 개발자는 일을 제대로 할 수 없으므로 데이터베이스가 잘못된 데이터로 채워지지 않도록하는 것은 좋은 일입니다.
이상적인 환경에서는 자연 조인이 열 이름과 일치하는 대신 관계 (예 : FK 제약 조건)를 사용합니다. 이것은 FK를 더욱 유용하게 만들 것입니다.
개인적으로 저는 외래 키가 테이블 간의 관계를 공식화하기 때문에 선호합니다. 귀하의 질문은 프로그래머가 참조 무결성을 위반하는 데이터를 도입하지 않는다고 가정한다는 것을 알고 있지만 최선의 의도에도 불구하고 데이터 참조 무결성이 위반되는 사례를 너무 많이 보았습니다!
사전 외래 키 제약 (선언적 참조 무결성 또는 DRI라고도 함)은 트리거를 사용하여 이러한 관계를 구현하는 데 많은 시간을 소비했습니다. 선언적 제약으로 관계를 공식화 할 수 있다는 사실은 매우 강력합니다.
@John-다른 데이터베이스는 외래 키에 대한 인덱스를 자동으로 만들 수 있지만 SQL Server는 그렇지 않습니다. SQL Server에서 외래 키 관계는 제약 일뿐입니다. 외래 키에 대한 인덱스를 별도로 정의해야합니다 (유용 할 수 있음).
편집 : IMO, ON DELETE 또는 ON UPDATE CASCADE를 지원하는 외래 키 사용이 반드시 좋은 것은 아닙니다. 실제로는 데이터의 관계를 기반으로 삭제시 캐스케이드를 신중하게 고려해야한다는 사실을 발견했습니다. 예를 들어 이것이 괜찮을 수있는 자연스러운 부모-자식이 있거나 관련 테이블이 조회 값 집합 인 경우입니다. 계단식 업데이트를 사용하면 한 테이블의 기본 키를 수정할 수 있음을 의미합니다. 이 경우 테이블의 기본 키가 변경되어서는 안된다는 일반적인 철학적 불일치가 있습니다. 키는 본질적으로 일정해야합니다.
데이터베이스에 의해 시행되는 외래 키 제약 에 대해 이야기하고 있다고 가정 합니다 . 아마도 이미 외래 키를 사용하고있을 것이고, 데이터베이스에 그것에 대해 말하지 않았을 것입니다.
프로그래머가 실제로이 작업을 이미 올바른 방식으로 수행하고 있다고 가정하면 외래 키 개념이 정말로 필요합니까?
이론적으로는 그렇지 않습니다. 그러나 버그가없는 소프트웨어는 없었습니다.
응용 프로그램 코드의 버그는 일반적으로 그렇게 위험하지 않습니다. 버그를 식별하고 수정하면 응용 프로그램이 다시 원활하게 실행됩니다. 그러나 버그로 인해 중단 된 데이터가 데이터베이스에 들어갈 수 있다면 그 문제에 갇혀 있습니다! 데이터베이스의 손상된 데이터를 복구하는 것은 매우 어렵습니다.
FogBugz 의 미묘한 버그로 인해 손상된 외래 키가 데이터베이스에 기록 될 수 있는지 고려하십시오 . 버그를 수정하고 버그 수정 릴리스에서 고객에게 신속하게 수정 사항을 푸시하는 것이 쉬울 수 있습니다. 그러나 수십 개의 데이터베이스에서 손상된 데이터를 어떻게 수정해야합니까? 외래 키의 무결성에 대한 가정이 더 이상 유지되지 않기 때문에 올바른 코드가 갑자기 깨질 수 있습니다.
웹 응용 프로그램에서는 일반적으로 데이터베이스와 대화하는 프로그램이 하나만 있으므로 버그로 인해 데이터가 손상 될 수있는 곳은 한 곳뿐입니다. 엔터프라이즈 애플리케이션에는 동일한 데이터베이스에 대해 말하는 여러 독립 애플리케이션이있을 수 있습니다 (데이터베이스 쉘로 직접 작업하는 사람은 말할 것도 없습니다). 모든 애플리케이션이 항상 그리고 영원히 버그없이 동일한 가정을 따르도록 할 수있는 방법은 없습니다.
제약 조건이 데이터베이스에 인코딩 된 경우 버그로 인해 발생할 수있는 최악의 상황은 사용자에게 일부 SQL 제약 조건이 충족되지 않았다는 추악한 오류 메시지가 표시되는 것 입니다. 이는 데이터를 엔터프라이즈 데이터베이스로 전송하는 것 보다 훨씬 선호되며,이 경우 모든 애플리케이션이 중단되거나 모든 종류의 잘못되거나 오해의 소지가있는 출력이 발생합니다.
아, 외래 키 제약 조건도 기본적으로 인덱싱되므로 성능이 향상됩니다. 외래 키 제약 조건을 사용 하지 않는 이유를 생각할 수 없습니다 .
FK는 매우 중요하며 eBay가 아니라면 항상 스키마에 존재해야합니다 .
unibrow
어떤 시점에서 어떤 한 가지 가 유효한 관계를 보장해야 한다고 생각 합니다.
예를 들어 Ruby on Rails 는 외래 키를 사용하지 않지만 모든 관계 자체의 유효성을 검사합니다. Ruby on Rails 애플리케이션에서만 데이터베이스에 액세스 할 수 있다면 괜찮습니다.
그러나 데이터베이스에 쓰는 다른 클라이언트가있는 경우 외래 키없이 자체 유효성 검사를 구현해야합니다. 그런 다음 거의 다른 유효성 검사 코드 사본 두 개를 갖게되는데, 이는 프로그래머라면 누구나 근본적인 죄라고 말할 수 있어야합니다.
이 시점에서 외래 키를 사용하면 책임을 다시 단일 지점으로 이동할 수 있으므로 실제로 필요합니다.
내가 아는 한, 외래 키는 프로그래머가 데이터를 올바른 방식으로 조작하도록 돕는 데 사용됩니다.
FK를 사용하면 DBA는 프로그래머 가 그렇게하지 않을 때 사용자의 더듬 거리는 것으로부터 데이터 무결성 을 보호하고 때로는 프로그래머의 더듬 거리는 것으로부터 보호 할 수 있습니다.
프로그래머가 실제로이 작업을 이미 올바른 방식으로 수행하고 있다고 가정하면 외래 키 개념이 정말로 필요합니까?
프로그래머는 필사적이고 오류가 있습니다. FK는 선언적 이므로 실수하기가 더 어렵습니다.
외래 키에 대한 다른 용도가 있습니까? 여기에 뭔가 빠졌나요?
이것이 만들어진 이유는 아니지만 FK는 다이어그램 작성 도구와 쿼리 빌더에 강력하고 안정적인 힌트를 제공합니다. 이것은 강력하고 신뢰할 수있는 힌트가 절실히 필요한 최종 사용자에게 전달됩니다.
애플리케이션이 데이터베이스에서 데이터를 조작 할 수있는 유일한 방법은 아니기 때문에 중요합니다. 응용 프로그램은 참조 무결성을 원하는대로 정직하게 처리 할 수 있지만 데이터베이스 수준에서 삽입, 삭제 또는 업데이트 명령을 실행하고 실행하는 데 적합한 권한을 가진 한 명의 bozo 만 있으면됩니다. 모든 응용 프로그램 참조 무결성 시행은 우회됩니다. FK 제약 조건을 데이터베이스 수준에 넣는 것은 명령을 실행하기 전에 FK 제약 조건을 비활성화하도록 선택하지 않는 한 FK 제약 조건으로 인해 잘못된 삽입 / 업데이트 / 삭제 문이 참조 무결성 위반과 함께 실패하게됩니다.
비용 / 이익 측면에서 생각해 보겠습니다 . MySQL 에서 제약 조건을 추가하는 것은 DDL 의 단일 추가 라인입니다 . 몇 개의 핵심 단어와 몇 초의 생각 일뿐입니다. 제 생각에는 그게 유일한 "비용"입니다 ...
도구는 외래 키를 좋아합니다. 외래 키는 비즈니스 논리 또는 기능에 영향을주지 않을 수있는 잘못된 데이터 (즉, 고아 행)를 방지하므로 눈에 띄지 않고 축적됩니다. 또한 스키마에 익숙하지 않은 개발자가 관계가 없다는 사실을 깨닫지 못하고 전체 작업 청크를 구현하는 것을 방지합니다. 아마도 현재 애플리케이션의 범위 내에서 모든 것이 훌륭 할 수도 있지만, 무언가를 놓치고 언젠가 예상치 못한 무언가가 추가되면 (멋진보고를 생각해보세요) 처음부터 축적 된 잘못된 데이터를 수동으로 정리해야하는 지점에있을 수 있습니다. 데이터베이스 강제 검사없이 스키마의.
모든 것을 정리할 때 이미 머릿속에있는 것을 성문화하는 데 걸리는 시간이 조금만 소요되는 것만으로도 몇 달 또는 몇 년 동안 많은 슬픔을 겪을 수 있습니다.
질문:
외래 키에 대한 다른 용도가 있습니까? 여기에 뭔가 빠졌나요?
약간로드되었습니다. "외래 키"대신 주석, 들여 쓰기 또는 변수 이름 지정 ... 문제의 내용을 이미 완벽하게 이해했다면 "사용 안 함"입니다.
엔트로피 감소. 데이터베이스에서 혼란스러운 시나리오가 발생할 가능성을 줄입니다. 우리는 모든 가능성을 고려하기 때문에 어려움을 겪고 있습니다. 그래서 제 생각에는 엔트로피 감소가 모든 시스템의 유지 관리의 핵심이라고 생각합니다.
예를 들어 가정을 할 때 : 각 주문에는 어떤 것에 의해 가정이 시행되어야한다는 고객이 있습니다 . 데이터베이스에서 "무언가"는 외래 키입니다.
나는 이것이 개발 속도에서 절충할만한 가치가 있다고 생각합니다. 물론, 당신은 그것들을 끄고 더 빨리 코딩 할 수 있고 이것이 아마도 일부 사람들이 그것을 사용하지 않는 이유 일 것입니다. 개인적으로 나는 NHibernate 와 내가 어떤 작업을 수행 할 때 화를내는 외래 키 제약으로 몇 시간을 죽였다 . 그러나 나는 문제가 무엇인지 알고 있으므로 문제가 적습니다. 저는 일반 도구를 사용하고 있으며이 문제를 해결하는 데 도움이되는 리소스가 있습니다.
대안은 외래 키가 설정되지 않고 데이터가 일관성이없는 시스템에 버그가 침투하도록 허용하는 것입니다 (충분한 시간이 주어지면). 그런 다음 비정상적인 버그 보고서를 받고 조사하고 "OH"합니다. 데이터베이스가 망가졌습니다. 이제 고치는 데 얼마나 걸립니까?
현재 우리는 외래 키를 사용하지 않습니다. 그리고 대부분 우리는 그것을 후회하지 않습니다.
즉, 우리는 유사한 이유로 인해 몇 가지 이유로 가까운 장래에 더 많이 사용하기 시작할 것입니다.
다이어그램. 외래 키 관계가 올바르게 사용되면 데이터베이스 다이어그램을 생성하는 것이 훨씬 쉽습니다.
도구 지원. 적절한 외래 키 관계가있는 경우 LINQ to SQL에 사용할 수있는 Visual Studio 2008 을 사용하여 데이터 모델을 빌드하는 것이 훨씬 쉽습니다 .
그래서 내 요점은 우리가 많은 수동 SQL 작업 (쿼리 생성, 쿼리 실행, blahblahblah)을 많이 수행하는 경우 외래 키가 반드시 필수적인 것은 아니라는 것을 발견했다는 것입니다. 하지만 도구를 사용하기 시작하면 훨씬 더 유용 해집니다.
외래 키 제약 조건 (및 일반적으로 제약 조건)에 대한 가장 좋은 점은 쿼리를 작성할 때 이러한 제약 조건에 의존 할 수 있다는 것입니다. "참"을 유지하는 데이터 모델에 의존 할 수 없다면 많은 쿼리가 훨씬 더 복잡해질 수 있습니다.
코드에서는 일반적으로 어딘가에서 예외가 발생하지만 SQL에서는 에서는 일반적으로 "잘못된"답변 만 제공됩니다.
이론적으로 SQL Server 는 쿼리 계획의 일부로 제약 조건을 사용할 수 있지만 분할을위한 검사 제약 조건을 제외하고는 실제로이를 목격했다고 말할 수 없습니다.
외래 키는 내가 작업 한 프로젝트 (비즈니스 응용 프로그램 및 소셜 네트워킹 웹 사이트)에서 선언 된 적이 없었습니다 (FOREIGN KEY REFERENCES 테이블 (열)).
그러나 항상 외래 키인 열 명명 규칙이있었습니다.
데이터베이스 정규화 와 비슷 합니다. 수행중인 작업과 그 결과 (주로 성능)를 알아야합니다.
외래 키의 장점 (데이터 무결성, 외래 키 열 색인, 데이터베이스 스키마를 알고있는 도구)의 장점을 알고 있지만 일반적으로 외래 키를 사용하는 것이 두렵습니다.
또한 다양한 데이터베이스 엔진이 다른 방식으로 외래 키를 제공 할 수 있으므로 마이그레이션 중에 미묘한 버그가 발생할 수 있습니다.
ON DELETE CASCADE를 사용하여 삭제 된 고객의 모든 주문 및 송장을 제거하는 것은보기 좋지만 잘못 설계된 데이터베이스 스키마의 완벽한 예입니다.
예. ON DELETE [RESTRICT | CASCADE]는 개발자가 데이터를 낭비하지 않도록하여 데이터를 깨끗하게 유지합니다. 저는 최근 외래 키와 같은 데이터베이스 제약에 초점을 맞추지 않은 Rails 개발자 팀에 합류했습니다.
다행스럽게도 다음을 발견했습니다. http://www.redhillonrails.org/foreign_key_associations.html-Ruby on Rails 플러그인의 RedHill은 구성 스타일에 대한 규칙을 사용하여 외래 키를 생성 합니다 . product_id 를 사용하여 마이그레이션 하면 제품 테이블 의 ID 에 대한 외래 키가 생성됩니다 .
트랜잭션으로 래핑 된 마이그레이션을 포함하여 RedHill 에서 다른 훌륭한 플러그인을 확인하십시오 .