다시 우리는 간다. 오래된 논쟁은 여전히 일어난다 ...
비즈니스 키를 기본 키로 사용하는 것이 좋을까요, 아니면 비즈니스 키 필드에 고유 한 제약 조건이있는 대리 ID (예 : SQL Server ID)를 사용 하시겠습니까?
이론을 뒷받침하는 예 또는 증거를 제공하십시오.
다시 우리는 간다. 오래된 논쟁은 여전히 일어난다 ...
비즈니스 키를 기본 키로 사용하는 것이 좋을까요, 아니면 비즈니스 키 필드에 고유 한 제약 조건이있는 대리 ID (예 : SQL Server ID)를 사용 하시겠습니까?
이론을 뒷받침하는 예 또는 증거를 제공하십시오.
답변:
양자 모두. 케이크를 가지고 먹습니다.
기본 키에는 레이블이 붙어 있다는 점을 제외하고는 특별한 것이 없습니다. NOT NULL UNIQUE 제약 조건에 지나지 않으며 테이블에는 둘 이상이있을 수 있습니다.
서로 게이트 키를 사용하는 경우에도 비즈니스 규칙에 따라 고유성을 보장하기 위해 비즈니스 키를 원합니다.
대리 키를 사용하는 몇 가지 이유는 다음과 같습니다.
안정성 : 비즈니스 또는 자연적인 요구로 인해 키를 변경하면 관련 테이블에 부정적인 영향을 미칩니다. 값과 관련된 의미가 없으므로 대리 키는 거의 변경되지 않습니다.
Convention : 다양한 PK 이름으로 테이블을 조인하는 방법을 생각하지 않고 표준화 된 기본 키 열 명명 규칙을 사용할 수 있습니다.
속도 : PK 값 및 유형에 따라 정수의 서로 게이트 키가 더 작아 색인 및 검색 속도가 더 빠를 수 있습니다.
비 대리 ( "자연스러운"말을 주저하는) 키를 지원하는 사람은 아직 아무도 말하지 않은 것 같습니다. 그래서 여기에 ...
대리 키 의 단점 은 무의미하다는 것입니다 (일부 사람들에게는 이점으로 인용되었지만 ...). 이로 인해 실제로 필요한 것보다 훨씬 많은 테이블을 쿼리에 조인 할 수 있습니다. 비교:
select sum(t.hours)
from timesheets t
where t.dept_code = 'HR'
and t.status = 'VALID'
and t.project_code = 'MYPROJECT'
and t.task = 'BUILD';
에 맞서:
select sum(t.hours)
from timesheets t
join departents d on d.dept_id = t.dept_id
join timesheet_statuses s on s.status_id = t.status_id
join projects p on p.project_id = t.project_id
join tasks k on k.task_id = t.task_id
where d.dept_code = 'HR'
and s.status = 'VALID'
and p.project_code = 'MYPROJECT'
and k.task_code = 'BUILD';
다음과 같은 아이디어를 진지하게 생각하지 않는 사람이 있습니까?
select sum(t.hours)
from timesheets t
where t.dept_id = 34394
and t.status_id = 89
and t.project_id = 1253
and t.task_id = 77;
"하지만"누군가 MYPROJECT, VALID 또는 HR 코드가 변경되면 어떻게됩니까? 이는 내 대답은 다음과 같습니다 "당신은 왜 할 필요 를 변경할 수 있나요?" 이것들은 "외부"키가 'VALID'를 'GOOD'로 다시 코딩해야한다는 입법에 따라 "자연적인"키가 아닙니다. "자연"키 중 적은 비율 만이 실제로 해당 범주에 속합니다. 일반적인 예는 SSN 및 우편 번호입니다. Person, Address와 같은 테이블에는 의미가없는 숫자 키를 사용하지만 모든 것은 아닙니다. 어떤 이유로 든 대부분의 사람들이 옹호하는 것처럼 보입니다.
또한보십시오 : 다른 질문에 대한 나의 대답
대리 키 (일반적으로 정수)는 테이블 관계를보다 빠르고 효율적으로 저장 및 업데이트 속도를 높이는 부가 가치를 제공합니다 (비즈니스 키 필드와 달리 대리 키를 사용할 때 외래 키를 업데이트 할 필요가없는 경우도 있음) 지금은 바뀌고 있습니다).
테이블의 기본 키는 주로 조인 목적으로 행을 고유하게 식별하는 데 사용해야합니다. Persons 테이블을 생각해보십시오. 이름은 변경 될 수 있으며 고유하지는 않습니다.
Think Companies : 당신은 Merkia의 다른 회사들과 사업을하는 행복한 Merkin 회사입니다. 회사 이름을 기본 키로 사용하지 않을 정도로 영리하므로 Merkia 정부 고유의 회사 ID를 10 자의 영숫자 문자로 사용하십시오. 그런 다음 Merkia는 회사 ID가 좋은 생각이라고 생각하여 회사 ID를 변경합니다. DB 엔진의 계단식 업데이트 기능을 사용하면 처음에는 관여하지 않아야 할 변경 사항을 사용할 수 있습니다. 나중에 비즈니스가 확장되고 이제 Freedonia의 회사와 협력합니다. Freedonian 회사 ID는 최대 16 자입니다. 회사 ID 기본 키 (주문, 발행, MoneyTransfers 등의 외래 키 필드)를 확대하고 기본 키 (외래 키)에 국가 필드를 추가해야합니다. 아야! 프리 도니아 내전 3 개국으로 나뉘어있다. 직원의 국가 이름은 새로운 국가 이름으로 변경해야합니다. 구조에 대한 계단식 업데이트. BTW, 기본 키는 무엇입니까? (국가, 회사 ID) 또는 (회사 ID, 국가)? 후자는 조인을 지원하고 전자는 다른 인덱스를 피합니다 (또는 주문을 국가별로 그룹화해야하는 경우도 많음).
이들 모두가 증거는 아니지만 조인 작업을 포함하여 모든 용도의 행을 고유하게 식별하기위한 대리 키가 비즈니스 키보다 선호됨을 나타냅니다.
나는 일반적으로 대리 키가 싫어. 유효한 자연 키가없는 경우에만 사용해야합니다. 의미없는 데이터를 테이블에 추가하면 상황이 개선 될 수 있다고 생각하는 것은 다소 터무니없는 일입니다.
내 이유는 다음과 같습니다.
자연 키를 사용하는 경우 테이블은 가장 자주 검색되는 방식으로 클러스터링되므로 쿼리 속도가 빨라집니다.
서로 게이트 키를 사용하는 경우 논리 키 열에 고유 인덱스를 추가해야합니다. 여전히 논리적 중복 데이터를 방지해야합니다. 예를 들어, pk가 서로 게이트 ID 열인 경우에도 조직 테이블에서 동일한 이름을 가진 두 조직을 허용 할 수 없습니다.
서로 게이트 키를 기본 키로 사용하면 기본 키가 무엇인지 명확하지 않습니다. 개발할 때 테이블을 고유하게 만드는 열 집합을 알고 싶습니다.
일대 다 관계 체인에서 논리 키 체인. 예를 들어 조직에는 많은 계정이 있고 계정에는 많은 송장이 있습니다. 따라서 Organization의 논리 키는 OrgName입니다. 계정의 논리 키는 OrgName, AccountID입니다. 송장의 논리 키는 OrgName, AccountID, InvoiceNumber입니다.
서로 게이트 키를 사용하는 경우 바로 상위 키에 외래 키만 있으면 키 체인이 잘립니다. 예를 들어 송장 테이블에는 OrgName 열이 없습니다. AccountID에 대한 열만 있습니다. 지정된 조직에 대한 송장을 검색하려면 조직, 계정 및 송장 테이블에 가입해야합니다. 논리 키를 사용하면 Organization 테이블을 직접 쿼리 할 수 있습니다.
조회 테이블의 서로 게이트 키 값을 저장하면 테이블에 의미없는 정수가 채워집니다. 데이터를 보려면 모든 조회 테이블에 조인하는 복잡한보기를 작성해야합니다. 찾아보기 테이블은 열에 허용되는 값 세트를 보유하기위한 것입니다. 대신 정수 서로 게이트 키를 저장하여 코드화해서는 안됩니다. 정규화 규칙에는 값 자체 대신 서로 게이트 정수를 저장해야한다는 제안이 없습니다.
세 가지 다른 데이터베이스 북이 있습니다. 그들 중 누구도 대리 키를 사용하는 것을 보여주지 않습니다.
자연과 대리의 핵심 딜레마에 대한이 끝없는 전쟁에 대한 경험을 나누고 싶습니다. 나는 생각 을 모두 대리 키 (인공 자동으로 생성 된 것)과 (도메인 의미 컬럼 (들로 구성)) 자연 키가 장점 과 단점 . 따라서 상황에 따라 방법 중 하나를 선택하는 것이 더 관련이있을 수 있습니다.
많은 사람들이 대리 키를 가장 완벽한 솔루션으로 제시하고 자연 키를 전염병으로 제시하는 것처럼, 다른 관점의 주장에 중점을 둘 것입니다.
대리 키는 다음과 같습니다.
관련이있는 경우 자연 키를 사용하고 키를 사용하는 것이 좋을 때는 대리 키를 사용하십시오.
이것이 누군가를 도왔기를 바랍니다!
비즈니스 의미가없는 키를 항상 사용하십시오. 좋은 습관 일뿐입니다.
편집 : 온라인으로 링크를 찾으려고했지만 할 수 없었습니다. 그러나 '엔터프라이즈 아키텍처 패턴 (Patterns of Enterprise Archtecture)' [Fowler]에는 키가 아닌 다른 의미로 키 이외의 다른 것을 사용해서는 안되는 이유에 대한 설명이 있습니다. 그것은 하나의 직업과 하나의 직업만을 가져야한다는 사실로 귀결됩니다.
ORM 도구를 사용하여 데이터 클래스를 처리 / 생성하려는 경우 대리 키가 매우 유용합니다. 고급 맵퍼 (읽기 : 최대 절전 모드)와 함께 복합 키를 사용할 수 있지만 코드에 약간의 복잡성이 추가됩니다.
물론 데이터베이스 순수 주의자들은 대리 키의 개념조차도 혐오 스럽다고 주장 할 것입니다.
적절한 경우 대리 키에 uid를 사용하는 팬입니다. 그들과의 주요 승리는 미리 키를 알고 있다는 것입니다. 예를 들어 ID가 이미 설정되어 있고 고유 한 것으로 보장 된 클래스의 인스턴스를 만들 수 있지만 정수 키를 사용하면 기본값 0 또는- 1을 저장 / 업데이트 할 때 적절한 값으로 업데이트하십시오.
UID는 조회 및 조인 속도 측면에서 불이익을 받으므로 해당 응용 프로그램이 바람직한 지 여부에 따라 다릅니다.
대체 키를 사용하면 변경 가능성이 전혀 없으므로 제 생각에 더 좋습니다. 내가 당신이 자연의 열쇠로 사용할 수 있다고 생각할 수있는 거의 모든 것이 변할 수 있습니다 (면책 조항 : 항상 사실은 아니지만 일반적으로).
예를 들어 자동차 DB 일 수 있습니다. 언뜻 보면, 번호판이 열쇠로 사용될 수 있다고 생각할 수 있습니다. 그러나 이것들은 변경되어 나쁜 생각이 될 수 있습니다. 당신 은 누군가가 당신에게 번호판을 그들의 반짝이는 새로운 개인화 된 번호판으로 바꿀 수없는 이유를 알고 싶어 할 때 앱 을 출시 한 후에 그것을 알고 싶지 않습니다.
languages
언어 코드 (ID)가 이미 테이블 에 있으므로 테이블 에 조인 할 필요가 없습니다 texts
.
비즈니스 정보가 변경되거나 동일 할 때 대리 키가 유용 할 수 있습니다. 비즈니스 이름은 전국적으로 고유 할 필요는 없습니다. Smith Electronics라는 두 개의 비즈니스를, 캔사스와 미시간에있는 두 개의 비즈니스를 처리한다고 가정하십시오. 주소별로 구분할 수 있지만 변경됩니다. 상태조차도 변할 수 있습니다. 캔사스 캔자스 시티의 스미스 일렉트로닉스가 강을 건너 미주리 주 캔자스 시티로 이사한다면 어떨까요? 자연적인 키 정보로 이러한 비즈니스를 구별 할 수있는 확실한 방법은 없으므로 대리 키가 매우 유용합니다.
서로 게이트 키를 ISBN 번호와 같이 생각하십시오. 일반적으로 제목과 저자별로 책을 식별합니다. 그러나 HP Willmott의 "Pearl Harbor"라는 제목의 두 권의 책이 있으며 다른 판이 아니라 확실히 다른 책입니다. 그런 경우에는 책의 모양 또는 초기 대 후반을 참조 할 수는 있지만 ISBN이 그대로 남아 있습니다.
다시 말해, SQL Server는 이러한 데이터를 물리적으로 정렬 할 수 없으므로 임의의 서로 게이트 키 (XY8D7-DFD8S를 읽는 GUID)에 클러스터형 인덱스를 배치하는 것은 좋지 않습니다. 대신 이러한 데이터에 고유 인덱스를 배치해야하지만, 기본 테이블 조작에 대해 SQL 프로파일 러를 실행 한 다음 해당 데이터를 데이터베이스 엔진 튜닝 관리자에 배치하는 것이 유리할 수도 있습니다.
사례 1 : 테이블이 조회 테이블입니다 유형이 50 개 미만인 (삽입)
비즈니스 / 자연 키를 사용하십시오 . 예를 들어 :
Table: JOB with 50 inserts
CODE (primary key) NAME DESCRIPTION
PRG PROGRAMMER A programmer is writing code
MNG MANAGER A manager is doing whatever
CLN CLEANER A cleaner cleans
...............
joined with
Table: PEOPLE with 100000 inserts
foreign key JOBCODE in table PEOPLE
looks at
primary key CODE in table JOB
사례 2 : 테이블은 수천 개의 삽입물 테이블입니다
대리 / 자동 증가 키를 사용하십시오 . 예를 들어 :
Table: ASSIGNMENT with 1000000 inserts
joined with
Table: PEOPLE with 100000 inserts
foreign key PEOPLEID in table ASSIGNMENT
looks at
primary key ID in table PEOPLE (autoincrement)
첫 번째 경우 :
두 번째 경우 :
코스 말. 내 편견을 진술하기 위해; 저는 개발자이기 때문에 주로 사용자에게 작업 응용 프로그램을 제공하는 것에 관심이 있습니다.
나는 자연스러운 키가있는 시스템에서 일했으며 값 변경이 파급되도록 많은 시간을 소비해야했습니다.
대리 키만있는 시스템에서 작업 한 결과 유일한 단점은 분할에 대한 비정규 화 된 데이터가 부족하다는 점이었습니다.
필자가 작업했던 대부분의 기존 PL / SQL 개발자는 조 인당 테이블 수로 인해 서로 게이트 키를 좋아하지 않았지만 테스트 및 프로덕션 데이터베이스는 결코 땀을 흘리지 않았습니다. 추가 조인은 응용 프로그램 성능에 영향을 미치지 않았습니다. "Xa = Yb의 X 내부 조인 Y = Yb"와 같은 절을 지원하지 않는 데이터베이스 방언 또는 해당 구문을 사용하지 않는 개발자의 경우, 서로 게이트 키에 대한 추가 조인은 쿼리를 읽기 어렵고 입력하기가 더 길어집니다. 확인 : @Tony Andrews 게시물을 참조하십시오. 그러나 ORM 또는 다른 SQL 생성 프레임 워크를 사용하면이를 알 수 없습니다. 터치 타이핑도 완화됩니다.
이 주제와 완전히 관련이 없지만 대리 키를 다루는 두통이있을 수 있습니다. Oracle 사전 제공 분석은웨어 하우스의 모든 차원 테이블에 자동 생성 SK를 생성하고 사실에이를 저장합니다. 따라서 새로운 열이 추가되거나 차원의 모든 항목에 대해 채워질 때마다 차원 (치수)을 다시로드해야 할 때마다 업데이트 중에 할당 된 SK가 SK를 사실에 저장된 원래 값과 동기화하지 못하도록합니다. 조인하는 모든 팩트 테이블을 완전히 다시로드합니다. SK가 무의미한 숫자 일지라도 원래 / 오래된 기록을 변경할 수없는 방법이있을 것입니다. 많은 사람들이 알다시피, 즉시 사용 가능한 것은 조직의 요구를 충족시키지 못하므로 지속적으로 사용자 정의해야합니다. 이제 창고에 3 년 분량의 데이터가 있습니다. Oracle Financial 시스템의 전체 재로드는 매우 큽니다. 따라서 필자의 경우 데이터 입력에서 생성되지 않지만 성능보고를 돕기 위해웨어 하우스에 추가됩니다. 나는 그것을 얻는다. 그러나 우리는 변화한다. 그리고 그것은 악몽이다.
특정 시점 데이터베이스의 경우 대리 키와 자연 키를 조합하는 것이 가장 좋습니다. 예를 들어 클럽의 회원 정보를 추적해야합니다. 멤버의 일부 속성은 변경되지 않습니다. 예 : 생년월일이지만 이름은 변경 될 수 있습니다. 따라서 member_id 서로 게이트 키로 Member 테이블을 작성하고 DOB에 대한 열을 갖습니다. person name이라는 다른 테이블을 작성하고 member_id, member_fname, member_lname, date_updated에 대한 열이 있습니다. 이 테이블에서 자연 키는 member_id + date_updated입니다.