대리 대 자연 / 비즈니스 키 [닫힘]


174

다시 우리는 간다. 오래된 논쟁은 여전히 ​​일어난다 ...

비즈니스 키를 기본 키로 사용하는 것이 좋을까요, 아니면 비즈니스 키 필드에 고유 한 제약 조건이있는 대리 ID (예 : SQL Server ID)를 사용 하시겠습니까?

이론을 뒷받침하는 예 또는 증거를 제공하십시오.


24
@Joachim Sauer : 어떤 것이 주관적인지 아닌지에 대한 논쟁은 문제의 주관성이나 주관성과 관련이없는 주관적 일 수 있습니다. 객관적인 무언가를 만드는 정확한 객관적인 기준을 제시 할 준비가되어 있지 않으면. 수염을 만드는 데 필요한 머리카락의 수와 같은 "개방형 개념"이라는 것이 있습니다. 턱 머리가없는 사람은 수염이없고 길이가 5,000 인치 인 사람은 수염이 있다고 객관적으로 말할 수 있지만, 중간 주관적인 판단의 어느 부분에서 객관적인 결정을 내려야합니다.
ErikE

@ Manrico : 당신은 이것을 스스로에게 물어봐야합니다 : 대리 키를 사용하지 않으면 기본 키가 여전히 불변합니까? 대답이 아니오 인 경우 대리 키 사용을 진지하게 고려해야합니다. 또한 기본 키가 사용자 입력으로 부분적으로 구성된 경우 서로 게이트 키 사용을 고려해야합니다. 왜? 데이터 이상이 발생할 위험이 있습니다.
code4life 2016 년

@TylerRick 그러나 이것은 완벽하게 좋은 질문은 아닙니다. 그것은 "종교적 전쟁"에 의해 입증 된 바와 같이, 아스카가 완벽하게 인식하고있는 것으로 알려진 바와 같이, 모든 상황에 일반적으로 적용 할 수있는 해결책을 요구합니다. .. "). 세상이 변했는지 궁금해하고 마지막으로 한쪽을 선택 해야하는 설득력있는 이유가 제공되는 대신 각 구체적인 상황에 대해이 질문을 계속해서 반복하고 확실하지 않은 경우 SO에 게시하는 것이 좋습니다 . 이것은 단지 교의를 이끌어냅니다.
MarioDS 2016 년

답변:


97

양자 모두. 케이크를 가지고 먹습니다.

기본 키에는 레이블이 붙어 있다는 점을 제외하고는 특별한 것이 없습니다. NOT NULL UNIQUE 제약 조건에 지나지 않으며 테이블에는 둘 이상이있을 수 있습니다.

서로 게이트 키를 사용하는 경우에도 비즈니스 규칙에 따라 고유성을 보장하기 위해 비즈니스 키를 원합니다.


7
여러 개의 "후보"키 (필드 또는 NULL이 아닌 동일한 크기의 필드 모음)가있는 경우 Boyce-Codd Normal Form을 위반할 가능성이 있습니다. BCNF는 3NF를 넘어서므로 많은 사람들이 걱정하지 않습니다. 그러나 BCNF에있는 것이 도움이되는 상황이 있습니다.
Alan

2
동의했다. 실제 질문은 : 테이블에 고유 한 대리 키를 추가해야합니까? 완전히 다른 질문은 논리 기본 키에 무엇을 사용해야 하는가입니다. 둘 다 본질적으로 null이 아닌 고유 인덱스 제약 조건입니다.
dkretz 2018

1
"모든 문제는 다른 수준의 간접 지향으로 해결됩니다"... 대리 키는 다음과 같습니다. 또 다른 간접 수준
Steve Schnepp

5
많은 의견이 대리 키없이 관계를 설정할 수 없다고 주장하는 것이 이상하다고 생각합니다. 대부분의 경우 대리 키는 불필요합니다. 왜 가치는 없지만 기술적 부채를 더하는 무언가를 추가해야 하는가? (그리고 경우에 따라 독특한 결과가 갑자기 고유하지 않게되는 이유)
Wil Moore III

2
NOT NULL UNIQUE 제약 조건을 초과했습니다. 기본 키는 데이터의 물리적 순서를 결정하는 클러스터형 인덱스로 사용됩니다. 일반적으로 Integer는 순차적으로 증가하고 데이터가 디스크의 EOF에 추가되므로 균형을 쉽게 잡을 수 있습니다. 당신은 텍스트 또는 GUID (UUID) 덜 순차적 데이터를 사용하는 경우 더 많은 디스크 IO 및 인덱스를 균형 노력이있을 것이다, 그 종류 큰 차이의 생각

124

대리 키를 사용하는 몇 가지 이유는 다음과 같습니다.

  1. 안정성 : 비즈니스 또는 자연적인 요구로 인해 키를 변경하면 관련 테이블에 부정적인 영향을 미칩니다. 값과 관련된 의미가 없으므로 대리 키는 거의 변경되지 않습니다.

  2. Convention : 다양한 PK 이름으로 테이블을 조인하는 방법을 생각하지 않고 표준화 된 기본 키 열 명명 규칙을 사용할 수 있습니다.

  3. 속도 : PK 값 및 유형에 따라 정수의 서로 게이트 키가 더 작아 색인 및 검색 속도가 더 빠를 수 있습니다.


2
이제 서로 게이트 키와 자연 키에 대해 많이 읽은 후에 서로 게이트 키를 사용하는 것이 더 좋습니다. 그러나 내 데이터베이스에서 자연 키 (NVARCHAR (20))는 고유해야합니다. 각 열에서 모든 데이터를 검사하여 각 삽입에서 값을 반복하지 않도록 (NOT NULL UNIQUE 제약 조건 사용) 더 많은 속도를 얻는 방법을 이해하지 못합니다.
VansFannel

70

비 대리 ( "자연스러운"말을 주저하는) 키를 지원하는 사람은 아직 아무도 말하지 않은 것 같습니다. 그래서 여기에 ...

대리 키 의 단점무의미하다는 것입니다 (일부 사람들에게는 이점으로 인용되었지만 ...). 이로 인해 실제로 필요한 것보다 훨씬 많은 테이블을 쿼리에 조인 할 수 있습니다. 비교:

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와 같은 테이블에는 의미가없는 숫자 키를 사용하지만 모든 것은 아닙니다. 어떤 이유로 든 대부분의 사람들이 옹호하는 것처럼 보입니다.

또한보십시오 : 다른 질문에 대한 나의 대답


14
-1 기본 키로서의 자연 키는 모든 자식 테이블에 대해 하나 이상의 필드 (대리 키의 경우 하나가 아닌)로 구성 될 수있는 부모 키와 자식을 추가해야한다는 문제가 있습니다. 키. 따라서 TABLEA에서 시작하여 관계가 1-0 .. * 인 다음을 상상해보십시오. 문제가 보입니까? 부모 키는 자식 테이블에 전파됩니다. TABLEA의 기본 키가 변경되면 어떻게됩니까? 이제 모든 하위 테이블 PK를 리팩터링해야합니다.
알프레도 오소리오

9
@Alfredo : 물론 그렇습니다. 그러나 20 년 이상의 경험에서 나는 테이블의 PK 변경에 대한 정의를 거의 보지 못했습니다. 그것이 정기적으로 일어난다면 아마도 자연 키도 피할 것입니다. 실제로 이런 일이 발생하는 매우 드문 경우에 나는 확장 된 영향을받을 준비가되어 있습니다.
Tony Andrews

10
동의하지 않습니다. 외부 키 (고객)가 자연 키를 편집해야하므로 시스템 전체에 전파되어야한다는 법이 종종 있습니다. 나는 이것이 정기적으로 일어나는 것을 본다. 키가 변경 될 필요가 없다는 것을 확신 할 수있는 유일한 방법은 정의상 의미가없는 경우입니다. 또한 최신 데이터베이스는 내부 조인을 매우 효율적으로 처리하므로 대리자를 사용하여 얻을 수있는 큰 공간 확보는 일반적으로 많은 내부 조인을 수행 할 필요가 없다는 이점을 능가합니다.
TTT

8
@TTT : 디자인이 처음에는 약했습니다. 다시 말하지만, 남자들이 소년들과 분리되어있는 곳입니다. 자연 키를 사용할시기와 대리자를 사용할시기를 올바르게 선택하십시오. 일반적인 교리가 아니라 테이블 단위로 결정합니다.
DanMan

7
나는 또한 20 년 이상의 경험을 가지고 있으며, 나는 당신의 의견을 두 번째입니다. 한 번은 대리 키를 사용하여 Oracle 데이터웨어 하우스를 만들었으며 데이터 유지 관리는 지옥과 같습니다. 단순히 데이터에 직접 액세스 할 수 없습니다. 항상 모든 것에 대한 쿼리를 작성해야하므로 대리 키를 처리하기가 끔찍합니다.
SQL Police

31

대리 키는 변경할 이유가 없습니다. 나는 자연 키에 대해 똑같이 말할 수 없습니다. 성, 이메일, ISBN 숫자가 모두 하루를 변경할 수 있습니다.


31

대리 키 (일반적으로 정수)는 테이블 관계를보다 빠르고 효율적으로 저장 및 업데이트 속도를 높이는 부가 가치를 제공합니다 (비즈니스 키 필드와 달리 대리 키를 사용할 때 외래 키를 업데이트 할 필요가없는 경우도 있음) 지금은 바뀌고 있습니다).

테이블의 기본 키는 주로 조인 목적으로 행을 고유하게 식별하는 데 사용해야합니다. Persons 테이블을 생각해보십시오. 이름은 변경 될 수 있으며 고유하지는 않습니다.

Think Companies : 당신은 Merkia의 다른 회사들과 사업을하는 행복한 Merkin 회사입니다. 회사 이름을 기본 키로 사용하지 않을 정도로 영리하므로 Merkia 정부 고유의 회사 ID를 10 자의 영숫자 문자로 사용하십시오. 그런 다음 Merkia는 회사 ID가 좋은 생각이라고 생각하여 회사 ID를 변경합니다. DB 엔진의 계단식 업데이트 기능을 사용하면 처음에는 관여하지 않아야 할 변경 사항을 사용할 수 있습니다. 나중에 비즈니스가 확장되고 이제 Freedonia의 회사와 협력합니다. Freedonian 회사 ID는 최대 16 자입니다. 회사 ID 기본 키 (주문, 발행, MoneyTransfers 등의 외래 키 필드)를 확대하고 기본 키 (외래 키)에 국가 필드를 추가해야합니다. 아야! 프리 도니아 내전 3 개국으로 나뉘어있다. 직원의 국가 이름은 새로운 국가 이름으로 변경해야합니다. 구조에 대한 계단식 업데이트. BTW, 기본 키는 무엇입니까? (국가, 회사 ID) 또는 (회사 ID, 국가)? 후자는 조인을 지원하고 전자는 다른 인덱스를 피합니다 (또는 주문을 국가별로 그룹화해야하는 경우도 많음).

이들 모두가 증거는 아니지만 조인 작업을 포함하여 모든 용도의 행을 고유하게 식별하기위한 대리 키가 비즈니스 키보다 선호됨을 나타냅니다.


가장 멋진 사용자 이름으로 모든 인터넷에서 승리하십시오!
Iain 홀더

1
이것은 공감대가 "나는 이것에 동의하지 않습니다."와 거의 같습니다.
jcollum

5
아래쪽 화살표의 툴팁에 "이 답변은 유용하지 않습니다"가 아니라 "동의하지 않습니다"라고 표시되어 있습니다. 아마도이 구체적인 대답에서 의미는 비슷하지만 일반적으로 동일하지는 않습니다.
tzot

1
누군가가 당신의 대답이 틀렸다고 생각한다면, 그것은 또한 질문자를 잘못된 방향 (올바른 방향과 반대)으로 이끌 것이라고 생각할 것이며, 따라서 당신의 대답은 "도움이되지 않는"것보다 더 나쁜 것으로 판단 할 것입니다, 그의 마음에 공감대를 정당화하는 것.
Erwin Smout

1
그렇습니다, 대리 열쇠는 질병입니다. 하나는 야생으로 유출되어 pkey로 사용하므로 이제 자신의 대리 키가 필요합니다. 그런 다음 키가 야생으로 유출되고 (예 : URL을 통해) 질병이 퍼집니다.
Samuel Danielson

25

나는 일반적으로 대리 키가 싫어. 유효한 자연 키가없는 경우에만 사용해야합니다. 의미없는 데이터를 테이블에 추가하면 상황이 개선 될 수 있다고 생각하는 것은 다소 터무니없는 일입니다.

내 이유는 다음과 같습니다.

  1. 자연 키를 사용하는 경우 테이블은 가장 자주 검색되는 방식으로 클러스터링되므로 쿼리 속도가 빨라집니다.

  2. 서로 게이트 키를 사용하는 경우 논리 키 열에 고유 인덱스를 추가해야합니다. 여전히 논리적 중복 데이터를 방지해야합니다. 예를 들어, pk가 서로 게이트 ID 열인 경우에도 조직 테이블에서 동일한 이름을 가진 두 조직을 허용 할 수 없습니다.

  3. 서로 게이트 키를 기본 키로 사용하면 기본 키가 무엇인지 명확하지 않습니다. 개발할 때 테이블을 고유하게 만드는 열 집합을 알고 싶습니다.

  4. 일대 다 관계 체인에서 논리 키 체인. 예를 들어 조직에는 많은 계정이 있고 계정에는 많은 송장이 있습니다. 따라서 Organization의 논리 키는 OrgName입니다. 계정의 논리 키는 OrgName, AccountID입니다. 송장의 논리 키는 OrgName, AccountID, InvoiceNumber입니다.

    서로 게이트 키를 사용하는 경우 바로 상위 키에 외래 키만 있으면 키 체인이 잘립니다. 예를 들어 송장 테이블에는 OrgName 열이 없습니다. AccountID에 대한 열만 있습니다. 지정된 조직에 대한 송장을 검색하려면 조직, 계정 및 송장 테이블에 가입해야합니다. 논리 키를 사용하면 Organization 테이블을 직접 쿼리 할 수 ​​있습니다.

  5. 조회 테이블의 서로 게이트 키 값을 저장하면 테이블에 의미없는 정수가 채워집니다. 데이터를 보려면 모든 조회 테이블에 조인하는 복잡한보기를 작성해야합니다. 찾아보기 테이블은 열에 허용되는 값 세트를 보유하기위한 것입니다. 대신 정수 서로 게이트 키를 저장하여 코드화해서는 안됩니다. 정규화 규칙에는 값 자체 대신 서로 게이트 정수를 저장해야한다는 제안이 없습니다.

  6. 세 가지 다른 데이터베이스 북이 있습니다. 그들 중 누구도 대리 키를 사용하는 것을 보여주지 않습니다.


7
필요할 때를 제외하고는 대리 키가 싫습니다. 엔터프라이즈에서 많은 오류가 발생할 수있는 자연 키를 사용하고 이러한 오류의 영향을받는 데이터베이스를 허용하지 않는 경우에 필요합니다.
Walter Mitty

26
-1 : 수십 개의 응용 프로그램을 작성하고 유지 관리했습니다. 가장 많은 데이터 관련 문제가있는 것은 자연 키를 사용하는 문제였습니다.
팔콘

6
포인트 중 일부는 대리 키가 PK이거나 클러스터 된 열이어야한다고 가정합니다. 사실이 아닙니다. 포인트 1과 5는 정수가 4 바이트이고 자연 키가 거의 항상 더 많고 더 많은 바이트라는 사실을 무시합니다. 그리고 클러스터되지 않은 각 인덱스는 클러스터 된 인덱스에있는 자연 키의 바이트를 반복해야하므로 자연 키 데이터베이스의 테이블과 인덱스는 페이지 당 훨씬 적은 수의 행을 갖게되어 읽기 성능 이 훨씬 저하 됩니다. 을 사용하면 쿼리가 더 빠르지 않고 느려집니다 .
ErikE

3
자연 키 (예 : 원자 번호, VIN 등)에 대한 또 다른 이유는 비즈니스 논리가 변경되어 데이터 유형이 증가 할 수 있습니다. 예 :-Before : Atoms의 추적 요금, After : Atoms 및 화합물의 추적 요금. 전 : 적재 능력에 대한 차량 추적. 이후 :화물 운반 능력을 위해 비행기, 보트, 자전거 및 사람 추가.
forforf December

3
기본 키가 1) 부분적으로 1) 변경 가능하고 변경 될 수있는 속성) 또는 2) 사용자 입력 (예 : 동적으로 생성 된 조회 목록)으로 구성되어있는 테이블이없는 것 같습니다. 키 불변성을 보장 할 수없는 경우 코드 또는 수동 "수정"스크립트를 통해 이러한 모든 엔티티 관계를 업데이트해야합니다. 당신이 그렇게하지 않아도된다면 ... 나는 당신의 데이터베이스가 키가없고 대단하지 않다고 생각한다.
code4life 2016 년

18

자연과 대리의 핵심 딜레마에 대한이 끝없는 전쟁에 대한 경험을 나누고 싶습니다. 나는 생각 을 모두 대리 키 (인공 자동으로 생성 된 것)과 (도메인 의미 컬럼 (들로 구성)) 자연 키가 장점단점 . 따라서 상황에 따라 방법 중 하나를 선택하는 것이 더 관련이있을 수 있습니다.

많은 사람들이 대리 키를 가장 완벽한 솔루션으로 제시하고 자연 키를 전염병으로 제시하는 것처럼, 다른 관점의 주장에 중점을 둘 것입니다.

서로 게이트 키의 단점

대리 키는 다음과 같습니다.

  1. 성능 문제의 원인 :
    • 일반적으로 자동 증분 열을 사용하여 구현되며 다음을 의미합니다.
      • 새로운 ID를 원할 때마다 데이터베이스 왕복 여행 (캐싱 또는 유사한 알고리즘을 사용하여이를 개선 할 수는 있지만 여전히 그 방법에는 자체 단점이 있음을 알고 있습니다).
      • 언젠가 하나의 스키마에서 다른 스키마로 데이터를 이동해야하는 경우 (적어도 회사에서는 정기적으로 발생) ID 충돌 문제가 발생할 수 있습니다. 그리고 네, UUID를 사용할 수 있지만 마지막 16 진수는 32 자리가 필요합니다! (데이터베이스 크기에 관심이 있다면 문제가 될 수 있습니다).
      • 모든 대리 키에 대해 하나의 시퀀스를 사용하는 경우 데이터베이스에서 경합이 발생합니다.
  2. 발생하기 쉬운 오류. 시퀀스에는 max_value 제한이 있으므로 개발자는 다음 사항에주의해야합니다.
    • 시퀀스를 순환시켜야합니다 (최대 값에 도달하면 1,2, ...로 돌아갑니다).
    • 시퀀스를 데이터의 순서대로 (시간이 지남에 따라) 사용하는 경우 사이클링의 경우를 처리해야합니다 (ID 1의 열이 ID 최대 값-1의 행보다 최신 일 수 있음).
    • 코드 (및 내부 ID로 간주되어서는 안되는 클라이언트 인터페이스조차도)가 시퀀스 값을 저장하는 데 사용 된 32b / 64b 정수를 지원하는지 확인하십시오.
  3. 중복되지 않은 데이터를 보장하지는 않습니다. 열 값은 같지만 생성 된 값이 다른 두 개의 행을 항상 가질 수 있습니다. 나를 위해입니다 보기의 데이터베이스 설계 관점에서 대리 키의 문제.
  4. 위키 백과에 대한 더 많은 정보 ...

자연스러운 열쇠에 대한 신화

  1. 복합 키는 서로 게이트 키보다 비효율적입니다. 아니! 사용 된 데이터베이스 엔진에 따라 다릅니다.
  2. 실제 키는 실제로 존재하지 않습니다. 죄송하지만 존재합니다! 항공 산업에서, 예를 들어, 다음 튜플은 주어진 예정된 항공편 (항공사, 출발 일자, 항공편 번호, 운항 접미사) 과 관련하여 항상 고유 합니다. 더 일반적으로, 비즈니스 데이터 세트가 주어진 표준에 의해 고유 한 것이 보장 될 때, 이 데이터 세트는 [좋은] 자연 키 후보입니다.
  3. 자연 키는 자식 테이블의 "스키마를 오염시킵니다". 나에게 이것은 실제 문제보다 느낌입니다. 각각 2 바이트의 4 열 기본 키를 갖는 것이 11 바이트의 단일 열보다 효율적일 수 있습니다. 또한, 4 개의 컬럼을 사용하여 상위 테이블에 조인하지 않고 하위 테이블을 직접 쿼리 할 수 ​​있습니다 (where 절에서 4 개의 컬럼을 사용하여).

결론

관련이있는 경우 자연 키를 사용하고 키를 사용하는 것이 좋을 때는 대리 키를 사용하십시오.

이것이 누군가를 도왔기를 바랍니다!


3
예정된 항공편의 출발 날짜를 다시 예약하면 어떻게됩니까? 모든 관련 엔티티를 추적하고 키를 삭제해야합니까, 아니면 실제로 관련 엔티티의 모든 키를 업데이트해야합니까? 아니면 단순한 단일 테이블 (3NF조차도 아님)을 다루고 있습니까?
code4life 2016 년

엑셀 런트 포인트 @ code4life
forcewill

@ code4life : 여기서는 operatingSuffix가 뛰어납니다. 클라이언트의 혼동을 피하기 위해 동일한 flightNumber를 유지하기 위해 접미사 (예 : 'D') 만 추가합니다.
mwnsiri

"항상 동일한 열 값을 갖지만 생성 된 값이 다른 두 개의 행을 가질 수 있으므로 열에 고유하거나 복합적인 고유 제한 조건을 두십시오.
wha7ever

15

비즈니스 의미가없는 키를 항상 사용하십시오. 좋은 습관 일뿐입니다.

편집 : 온라인으로 링크를 찾으려고했지만 할 수 없었습니다. 그러나 '엔터프라이즈 아키텍처 패턴 (Patterns of Enterprise Archtecture)' [Fowler]에는 키가 아닌 다른 의미로 키 이외의 다른 것을 사용해서는 안되는 이유에 대한 설명이 있습니다. 그것은 하나의 직업과 하나의 직업만을 가져야한다는 사실로 귀결됩니다.


22
Martin Fowler는 여러 가지 일 수 있지만 데이터베이스 디자인에 대한 권한은 없습니다.
Tony Andrews

결론에 도달하기 전에 몇 가지 추론을 제공해야한다고 생각합니다.
Arne Evertsson

4
@ArneEvertsoon 그 이유가 있습니다. '그것은 하나의 직업과 하나의 직업만을 가져야한다는 사실로 귀결됩니다.' 단일 책임.
Iain Holder

10

ORM 도구를 사용하여 데이터 클래스를 처리 / 생성하려는 경우 대리 키가 매우 유용합니다. 고급 맵퍼 (읽기 : 최대 절전 모드)와 함께 복합 키를 사용할 수 있지만 코드에 약간의 복잡성이 추가됩니다.

물론 데이터베이스 순수 주의자들은 대리 키의 개념조차도 혐오 스럽다고 주장 할 것입니다.

적절한 경우 대리 키에 uid를 사용하는 팬입니다. 그들과의 주요 승리는 미리 키를 알고 있다는 것입니다. 예를 들어 ID가 이미 설정되어 있고 고유 한 것으로 보장 된 클래스의 인스턴스를 만들 수 있지만 정수 키를 사용하면 기본값 0 또는- 1을 저장 / 업데이트 할 때 적절한 값으로 업데이트하십시오.

UID는 조회 및 조인 속도 측면에서 불이익을 받으므로 해당 응용 프로그램이 바람직한 지 여부에 따라 다릅니다.


6

대체 키를 사용하면 변경 가능성이 전혀 없으므로 제 생각에 더 좋습니다. 내가 당신이 자연의 열쇠로 사용할 수 있다고 생각할 수있는 거의 모든 것이 변할 수 있습니다 (면책 조항 : 항상 사실은 아니지만 일반적으로).

예를 들어 자동차 DB 일 수 있습니다. 언뜻 보면, 번호판이 열쇠로 사용될 수 있다고 생각할 수 있습니다. 그러나 이것들은 변경되어 나쁜 생각이 될 수 있습니다. 당신 은 누군가가 당신에게 번호판을 그들의 반짝이는 새로운 개인화 된 번호판으로 바꿀 수없는 이유를 알고 싶어 할 때 앱 출시 한 후에 그것을 알고 싶지 않습니다.


1
불행히도 자동차에는 변하지 않는 자연스러운 열쇠가 있습니다 : VIN (적어도 미국에서는 ...)
jcollum

@jcollum 네, 알겠습니다. 내 의견은 여전히 ​​설립되어 있지만 내 모범은 반드시 가능한 한 좋은 것은 아닙니다.
Mark Embling

2
ISO 코드를 기반으로 할 때 언어 목록은 자연 키의 예입니다. 따라서 특정 언어로 테이블의 내용을로드하려는 경우 languages언어 코드 (ID)가 이미 테이블 에 있으므로 테이블 에 조인 할 필요가 없습니다 texts.
DanMan

@ DanMan 나는 거기에 당신과 동의해야합니다. 자연스러운 키로 더 잘 작동하는 몇 가지 예가 항상 있습니다. 규칙이나 일반적인 접근법은 절대 절대가 아니며, 이것이 100 % 당신의 접근법으로 갈 것입니다 :-)
Mark Embling

5

가능하면 항상 하나의 열, 대리 키를 사용하십시오. 이렇게하면 레코드를 유지 관리하기 위해 단일 정보를 추적 할 책임이 있기 때문에 조인뿐만 아니라 삽입 / 업데이트 / 삭제도 훨씬 깔끔해집니다.

그런 다음 필요에 따라 비즈니스 키를 고유 한 제약 조건 또는 색인으로 쌓으십시오. 이렇게하면 데이터 무결성이 그대로 유지됩니다.

비즈니스 논리 / 자연 키는 변경 될 수 있지만 테이블의 기본 키는 절대 바뀌지 않아야합니다.


4

데이터웨어 하우스 시나리오에서 대리 키 경로를 따르는 것이 좋습니다. 두 가지 이유 :

  • 소스 시스템과 독립적이며 데이터 유형 변경과 같은 변경 사항은 영향을 미치지 않습니다.
  • 서로 게이트 키에 정수 데이터 유형 만 사용하므로 DW에는 물리적 공간이 덜 필요합니다. 또한 색인이 더 잘 작동합니다.

2

비즈니스 정보가 변경되거나 동일 할 때 대리 키가 유용 할 수 있습니다. 비즈니스 이름은 전국적으로 고유 할 필요는 없습니다. Smith Electronics라는 두 개의 비즈니스를, 캔사스와 미시간에있는 두 개의 비즈니스를 처리한다고 가정하십시오. 주소별로 구분할 수 있지만 변경됩니다. 상태조차도 변할 수 있습니다. 캔사스 캔자스 시티의 스미스 일렉트로닉스가 강을 건너 미주리 주 캔자스 시티로 이사한다면 어떨까요? 자연적인 키 정보로 이러한 비즈니스를 구별 할 수있는 확실한 방법은 없으므로 대리 키가 매우 유용합니다.

서로 게이트 키를 ISBN 번호와 같이 생각하십시오. 일반적으로 제목과 저자별로 책을 식별합니다. 그러나 HP Willmott의 "Pearl Harbor"라는 제목의 두 권의 책이 있으며 다른 판이 아니라 확실히 다른 책입니다. 그런 경우에는 책의 모양 또는 초기 대 후반을 참조 할 수는 있지만 ISBN이 그대로 남아 있습니다.


1
나는 당신의 모범에 동의하지 않는 것 같아요. ISBN 번호는 책의 속성입니다. 서로 게이트 키는 나머지 행 데이터와 독립적이므로이 위치는 ISBN이 이미 모든 책을 고유하게 식별하더라도 책 테이블에 대해 별도의 서로 게이트 키를 사용하여 옹호합니다.
Christopher Cashell

또는 ISBN을 대리 키 자체로 생각하십시오. 의미가없는 식별자이며 특정 책에 적용되는 코드 일뿐입니다. 책 테이블을 만드는 경우 ISBN이 기본 키일 수도 있습니다 (행마다 한 권의 책이 있고 항상 책이 있다고 가정).
David Thornley

@Christopher Cashell-1 년 전이 게시물을 보았지만 뭔가 추가 할 줄 알았습니다. ISBN은 고유하지 않을 수 있으며 중복 될 수 있습니다. 도서관에서 몇 년 동안 일한 친구가 있는데 종종 ISBN이 중복 된 책을 자주 봤습니다. 문제는 ISBN의 고유성이 모든 출판물의 모든 숫자를 보장하는 하나의 본문이 아니라 발행인에게 있다는 것입니다 독특하고 게시자가 항상 함께 행동 한 것은 아닙니다.
토머

2
1 년 전이 게시물을보고 ISBN이 실제로 자연스럽게 존재한다고 언급하고 싶었습니다. 서로 게이트 키와 달리 키 값 자체에 구워진 의미가 있습니다. 예를 들어 키의 일부는 게시자를 식별합니다. 또한 위에서 언급했듯이 고유 한 것은 아닙니다. 그들은되는 가정 고유해야하지만 고유성은 출판사에서 제공하고 그들은 항상 완벽하게되지 않았다.
토마스

기술적으로 기업은 국가 간을 이동할 수 없습니다. 새로운 상태로 새로운 회사가 만들어지고 자산이 이전됩니다. 그것은 데이터베이스 정보에도 적용됩니다.
Warren Dew 1

2

다시 말해, SQL Server는 이러한 데이터를 물리적으로 정렬 할 수 없으므로 임의의 서로 게이트 키 (XY8D7-DFD8S를 읽는 GUID)에 클러스터형 인덱스를 배치하는 것은 좋지 않습니다. 대신 이러한 데이터에 고유 인덱스를 배치해야하지만, 기본 테이블 조작에 대해 SQL 프로파일 러를 실행 한 다음 해당 데이터를 데이터베이스 엔진 튜닝 관리자에 배치하는 것이 유리할 수도 있습니다.

스레드 @ http://social.msdn.microsoft.com/Forums/en-us/sqlgetstarted/thread/27bd9c77-ec31-44f1-ab7f-bd2cb13129be 참조


SQL Server GUID 정렬 할 수 있다고 확신 합니다.
Michael Green

이것은 정확하지는 않지만 GUID를 평가할 수는 있지만 결과적으로 인간에게는 무의미하지 않습니다. stackoverflow.com/questions/7810602/…
Bryan Swan

1
사실이지만 "SQL Server는 실제로 정렬 할 수 없습니다"와는 다릅니다.
Michael Green

2

사례 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)

첫 번째 경우 :

  • 테이블 JOB과의 조인을 사용하지 않고 PEOPLE 테이블의 모든 프로그래머를 선택할 수 있지만 "SELECT * FROM PEOPLE WHERE JOBCODE = 'PRG'"만으로도 가능합니다.

두 번째 경우 :

  • 기본 키가 정수이므로 데이터베이스 쿼리가 더 빠릅니다.
  • 데이터베이스 자체가 다음 자동 증가를 제공하므로 다음 고유 키를 찾는 데 신경을 쓸 필요가 없습니다.

2

대리 키가 거의 항상 의미 가있는 경우 중 하나입니다 . 데이터베이스에 가장 적합한 것을 선택하거나 객체 모델에 가장 적합한 것을 선택하는 경우가 있지만 두 경우 모두 무의미한 키 또는 GUID를 사용하는 것이 좋습니다. 인덱싱이 더 쉽고 빠르며 변경되지 않는 객체의 정체성입니다.


1

코스 말. 내 편견을 진술하기 위해; 저는 개발자이기 때문에 주로 사용자에게 작업 응용 프로그램을 제공하는 것에 관심이 있습니다.

나는 자연스러운 키가있는 시스템에서 일했으며 값 변경이 파급되도록 많은 시간을 소비해야했습니다.

대리 키만있는 시스템에서 작업 한 결과 유일한 단점은 분할에 대한 비정규 화 된 데이터가 부족하다는 점이었습니다.

필자가 작업했던 대부분의 기존 PL / SQL 개발자는 조 인당 테이블 수로 인해 서로 게이트 키를 좋아하지 않았지만 테스트 및 프로덕션 데이터베이스는 결코 땀을 흘리지 않았습니다. 추가 조인은 응용 프로그램 성능에 영향을 미치지 않았습니다. "Xa = Yb의 X 내부 조인 Y = Yb"와 같은 절을 지원하지 않는 데이터베이스 방언 또는 해당 구문을 사용하지 않는 개발자의 경우, 서로 게이트 키에 대한 추가 조인은 쿼리를 읽기 어렵고 입력하기가 더 길어집니다. 확인 : @Tony Andrews 게시물을 참조하십시오. 그러나 ORM 또는 다른 SQL 생성 프레임 워크를 사용하면이를 알 수 없습니다. 터치 타이핑도 완화됩니다.


또한; 대리 키가 그저 그런 것만으로 실제로 집으로 돌아가려면 임의의 큰 숫자로 시작하고 시퀀스를 1이 아닌 3+ 씩 증가 시키십시오. 또는 동일한 시퀀스를 사용하여 둘 이상의 키에 대한 값을 생성하십시오.
WillC

1

이 주제와 완전히 관련이 없지만 대리 키를 다루는 두통이있을 수 있습니다. Oracle 사전 제공 분석은웨어 하우스의 모든 차원 테이블에 자동 생성 SK를 생성하고 사실에이를 저장합니다. 따라서 새로운 열이 추가되거나 차원의 모든 항목에 대해 채워질 때마다 차원 (치수)을 다시로드해야 할 때마다 업데이트 중에 할당 된 SK가 SK를 사실에 저장된 원래 값과 동기화하지 못하도록합니다. 조인하는 모든 팩트 테이블을 완전히 다시로드합니다. SK가 무의미한 숫자 일지라도 원래 / 오래된 기록을 변경할 수없는 방법이있을 것입니다. 많은 사람들이 알다시피, 즉시 사용 가능한 것은 조직의 요구를 충족시키지 못하므로 지속적으로 사용자 정의해야합니다. 이제 창고에 3 년 분량의 데이터가 있습니다. Oracle Financial 시스템의 전체 재로드는 매우 큽니다. 따라서 필자의 경우 데이터 입력에서 생성되지 않지만 성능보고를 돕기 위해웨어 하우스에 추가됩니다. 나는 그것을 얻는다. 그러나 우리는 변화한다. 그리고 그것은 악몽이다.


0

특정 시점 데이터베이스의 경우 대리 키와 자연 키를 조합하는 것이 가장 좋습니다. 예를 들어 클럽의 회원 정보를 추적해야합니다. 멤버의 일부 속성은 변경되지 않습니다. 예 : 생년월일이지만 이름은 변경 될 수 있습니다. 따라서 member_id 서로 게이트 키로 Member 테이블을 작성하고 DOB에 대한 열을 갖습니다. person name이라는 다른 테이블을 작성하고 member_id, member_fname, member_lname, date_updated에 대한 열이 있습니다. 이 테이블에서 자연 키는 member_id + date_updated입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.