다시 우리는 간다. 오래된 논쟁은 여전히 일어난다 …
비즈니스 키를 기본 키로 사용하는 것이 좋을까요, 아니면 비즈니스 키 필드에 고유 한 제약 조건이있는 대리 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와 같은 테이블에는 의미가없는 숫자 키를 사용하지만 모든 것은 아닙니다. 어떤 이유로 든 대부분의 사람들이 옹호하는 것처럼 보입니다.
또한보십시오 : 다른 질문에 대한 나의 대답
답변
대리 키는 변경할 이유가 없습니다. 나는 자연 키에 대해 똑같이 말할 수 없습니다. 성, 이메일, ISBN 숫자가 모두 하루를 변경할 수 있습니다.
답변
대리 키 (일반적으로 정수)는 테이블 관계를보다 빠르고 효율적으로 저장 및 업데이트 속도를 높이는 부가 가치를 제공합니다 (비즈니스 키 필드와 달리 대리 키를 사용할 때 외래 키를 업데이트 할 필요가없는 경우도 있음) 지금은 바뀌고 있습니다).
테이블의 기본 키는 주로 조인 목적으로 행을 고유하게 식별하는 데 사용해야합니다. 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 테이블을 직접 쿼리 할 수 있습니다.
-
조회 테이블의 서로 게이트 키 값을 저장하면 테이블에 의미없는 정수가 채워집니다. 데이터를 보려면 모든 조회 테이블에 조인하는 복잡한보기를 작성해야합니다. 찾아보기 테이블은 열에 허용되는 값 세트를 보유하기위한 것입니다. 대신 정수 서로 게이트 키를 저장하여 코드화해서는 안됩니다. 정규화 규칙에는 값 자체 대신 서로 게이트 정수를 저장해야한다는 제안이 없습니다.
-
세 가지 다른 데이터베이스 북이 있습니다. 그들 중 누구도 대리 키를 사용하는 것을 보여주지 않습니다.
답변
자연과 대리의 핵심 딜레마에 대한이 끝없는 전쟁에 대한 경험을 나누고 싶습니다. 나는 생각 을 모두 대리 키 (인공 자동으로 생성 된 것)과 (도메인 의미 컬럼 (들로 구성)) 자연 키가 장점 과 단점 . 따라서 상황에 따라 방법 중 하나를 선택하는 것이 더 관련이있을 수 있습니다.
많은 사람들이 대리 키를 가장 완벽한 솔루션으로 제시하고 자연 키를 전염병으로 제시하는 것처럼, 다른 관점의 주장에 중점을 둘 것입니다.
서로 게이트 키의 단점
대리 키는 다음과 같습니다.
- 성능 문제의 원인 :
- 일반적으로 자동 증분 열을 사용하여 구현되며 다음을 의미합니다.
- 새로운 ID를 원할 때마다 데이터베이스 왕복 여행 (캐싱 또는 유사한 알고리즘을 사용하여이를 개선 할 수는 있지만 여전히 그 방법에는 자체 단점이 있음을 알고 있습니다).
- 언젠가 하나의 스키마에서 다른 스키마로 데이터를 이동해야하는 경우 (적어도 회사에서는 정기적으로 발생) ID 충돌 문제가 발생할 수 있습니다. 그리고 네, UUID를 사용할 수 있지만 마지막 16 진수는 32 자리가 필요합니다! (데이터베이스 크기에 관심이 있다면 문제가 될 수 있습니다).
- 모든 대리 키에 대해 하나의 시퀀스를 사용하는 경우 데이터베이스에서 경합이 발생합니다.
- 일반적으로 자동 증분 열을 사용하여 구현되며 다음을 의미합니다.
- 발생하기 쉬운 오류. 시퀀스에는 max_value 제한이 있으므로 개발자는 다음 사항에주의해야합니다.
- 시퀀스를 순환시켜야합니다 (최대 값에 도달하면 1,2, …로 돌아갑니다).
- 시퀀스를 데이터의 순서대로 (시간이 지남에 따라) 사용하는 경우 사이클링의 경우를 처리해야합니다 (ID 1의 열이 ID 최대 값-1의 행보다 최신 일 수 있음).
- 코드 (및 내부 ID로 간주되어서는 안되는 클라이언트 인터페이스조차도)가 시퀀스 값을 저장하는 데 사용 된 32b / 64b 정수를 지원하는지 확인하십시오.
- 중복되지 않은 데이터를 보장하지는 않습니다. 열 값은 같지만 생성 된 값이 다른 두 개의 행을 항상 가질 수 있습니다. 나를 위해입니다 보기의 데이터베이스 설계 관점에서 대리 키의 문제.
- 위키 백과에 대한 더 많은 정보 …
자연스러운 열쇠에 대한 신화
- 복합 키는 서로 게이트 키보다 비효율적입니다. 아니! 사용 된 데이터베이스 엔진에 따라 다릅니다.
- 실제 키는 실제로 존재하지 않습니다. 죄송하지만 존재합니다! 항공 산업에서, 예를 들어, 다음 튜플은 주어진 예정된 항공편 (항공사, 출발 일자, 항공편 번호, 운항 접미사) 과 관련하여 항상 고유 합니다. 더 일반적으로, 비즈니스 데이터 세트가 주어진 표준에 의해 고유 한 것이 보장 될 때, 이 데이터 세트는 [좋은] 자연 키 후보입니다.
- 자연 키는 자식 테이블의 “스키마를 오염시킵니다”. 나에게 이것은 실제 문제보다 느낌입니다. 각각 2 바이트의 4 열 기본 키를 갖는 것이 11 바이트의 단일 열보다 효율적일 수 있습니다. 또한, 4 개의 컬럼을 사용하여 상위 테이블에 조인하지 않고 하위 테이블을 직접 쿼리 할 수 있습니다 (where 절에서 4 개의 컬럼을 사용하여).
결론
관련이있는 경우 자연 키를 사용하고 키를 사용하는 것이 좋을 때는 대리 키를 사용하십시오.
이것이 누군가를 도왔기를 바랍니다!
