it-swarm-ko.tech

대리 및 자연 / 비즈니스 키

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

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

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

163
Manrico Corazzi

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

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

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

91
Ted

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

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

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

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

113
Jay Shepherd

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

서로 게이트 키의 단점 무의미한 일부에서는 이점이 있지만 ...). 이로 인해 실제로 필요한 것보다 훨씬 많은 테이블을 쿼리에 조인 할 수 있습니다. 비교:

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

참조 : 다른 질문에 대한 나의 대답

67
Tony Andrews

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

29
Rimantas

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

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

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

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

29
tzot

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

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

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

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

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

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

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

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

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

26
Ken

자연과 대리의 핵심 딜레마에 대한이 끝없는 전쟁에 대한 나의 경험을 나누고 싶습니다. both 서로 게이트 키 (인공 자동 생성 키)와 자연 키 (도메인 의미의 열로 구성)는 proscons. 따라서 상황에 따라 방법 중 하나를 선택하는 것이 더 관련이있을 수 있습니다.

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

서로 게이트 키의 단점

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

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

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

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

결론

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

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

17
mwnsiri

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

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

15
Iain Holder

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

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

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

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

9
Derek Lawless

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

예를 들어 자동차 DB 일 수 있습니다. 언뜻 보면 번호판을 키로 사용할 수 있다고 생각할 수 있습니다. 그러나 이것들은 변경되어 나쁜 생각이 될 수 있습니다. 누군가가 앱을 출시 한 후 after 앱을 출시하려고하는 이유를 알고 싶지 않습니다. 반짝 이는 새로운 개인화 된 것.

6
Mark Embling

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

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

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

5
user7658

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

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

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

2
Charles Graham

다시 말해, 임의의 대리 키, 즉 XY8D7-DFD8S를 읽는 GUID에 클러스터 된 인덱스를 배치하는 것은 좋은 방법이 아닙니다. 대신 이러한 데이터에 고유 인덱스를 배치해야하지만, 기본 테이블 조작에 대해 SQL 프로파일 러를 실행 한 다음 해당 데이터를 데이터베이스 엔진 튜닝 관리자에 배치하는 것이 유리할 수도 있습니다.

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

2
Bryan Swan

Case 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

Case 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
Stefanos Kargas

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

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

2
David Thornley

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

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

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

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

1
WillC

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

1
lrb

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

0
kanad