데이터베이스에서 단일 기본 키 시퀀스를 공유 하시겠습니까?


14

주어진 테이블에서 고유 한 기본 키 대신 모든 테이블에서 고유 한 단일 키 대신 모든 테이블에서 단일 시퀀스를 기본 키로 사용하는 것이 허용 되는가? 그렇다면, 테이블에서 단일 기본 키 시퀀스를 사용하는 것보다 객관적으로 낫습니다.

저는 DBA가 아닌 주니어 소프트웨어 개발자이므로 여전히 훌륭한 데이터베이스 디자인의 많은 기초를 배우고 있습니다.

편집 : 누군가 궁금해하는 경우, 최근에 우리 회사의 DBA 중 한 사람이 데이터베이스 디자인에 대한 비판을 읽었습니다. 나는 지금까지 배웠다.

Edit2 : 의견의 질문에 대답하기 위해 이것은 Oracle 11g 용이지만 데이터베이스가 아닌 특정 수준에서 궁금합니다. 이 질문이 데이터베이스에 의존한다면 그 이유를 알고 싶지만 그런 경우에는 오라클에 대한 답변을 찾고 싶습니다.


2
성능상의 이유로 일반적으로 끔찍한 아이디어입니다.
Philᵀᴹ

1
실제로 각 테이블마다 독립적 인 기본 키 범위를 갖는 것이 더 큰 이점이 있습니다. 그러나 당신이 말할 수있는 많은 ID를 볼 때만, 이것은 하나의 계정, 하나는 PurchaseHeader 등입니다.이를 위해서는 약간의 설정이 필요하며 (특별한 목적과 마찬가지로) 지속적인 관리와 먹이가 필요합니다. (예, 몇 년 전에 이와 같은 시스템을 사용해 왔습니다.)
RLF

어떤 DBMS를 사용하고 있습니까? 신탁? Postgres? DB2?
a_horse_with_no_name

1
그가 의미 한 바를 잘못 해석했을 가능성이 있습니까? 어쩌면 그는 그 문자 그대로되지 않았습니까?
JamesRyan

회사 DBA가 실제로 테이블에 기본 키 필드가 없음을 의미 했습니까?
Max Vernon

답변:


13

괜찮습니까? 확실한. 흔한? 아니요? 유익한가요? 못 미더운.

이전 작업에서 중앙 시퀀스 생성기가있는 시스템을 상속했습니다 (이것은 오래 전에 SQL Server 시스템이었습니다). SEQUENCE SQL Server 2012에 도입 이었습니다). 실제로 성능 병목 현상은 아니며 초당 수십만 개의 값을 생성하지 않는 한해서는 안됩니다. 그러나 모든 코드를 아무 이유없이 복잡하게 만들었습니다. 디자인의 의도는 시스템의 무언가에 ID 값 12가 할당 된 경우 시스템에서 오직 하나의 ID 만 12를 가질 수 있다는 것을 확인하는 것이 었습니다. 이것은 나에게 상당히 모호한 것처럼 보였고 결코 이해하지 못했습니다. CustomerID = 12 인 고객이있는 경우 왜 OrderID = 12 인 주문이 불가능합니까?

여러 시스템이 있고 이러한 여러 시스템에서 특정 유형의 엔티티 (예 : 고객 또는 주문)에 대한 ID를 생성하는 경우 중앙 시퀀스 생성기의 유용성을 알 수 있습니다. 중앙 시퀀스는 병목 현상 (단일 실패 지점)이없고 동일한 ID를 생성하는 두 시스템에 대한 두려움없이 여러 시스템에 새로운 가치를 부여 할 수 있습니다.


이와 같은 것을 선택하고 고유 식별자를 기본 키로 사용하려는 경우 선호도가 있습니다 (응답은 "의존")? GUID는 자체 중앙 집중식 기본 키 생성기를 롤링하지 않고 표준 구현을 얻는 것을 제외하고는 동일한 방식으로 문제를 해결하는 것처럼 보입니다. 분명히 SQL 2012에서 시퀀스를 사용하면 두 가지를 모두 달성 할 수 있지만 누군가 이전 버전을 사용한다고 가정합니까?
SqlRyan

2
@SqlRyan OrderID가 CustomerID와 완전히 다른 이유를 이해해야합니다. 거의 확실하게 GUID를 사용하지 않을 것입니다. 코스 범위가 거의 다되었을 때 경고가 표시되면 IDENTITY 범위를 설정하는 것이 좋습니다 (고객은 1에서 시작, 주문은 1000000에서 시작 등).
Aaron Bertrand

1
@SqlRyan-잘못 구현 된 GUID를 클러스터 된 기본 키로 사용하면 모든 종류의 문제가 발생할 수 있습니다. Aaron이 말했듯이, IDENTITY는 목적에 훨씬 적합합니다.
Max Vernon

이전 시스템에서 전체 데이터베이스에서 단일 시퀀스를 사용하는 것을 보았습니다. 외래 키가 단일 테이블 대신 수많은 다른 테이블을 가리 키도록하기 위해 수행되었으므로 두 개의 다른 행의 외래 키를 말했을 때 12 살이었을 때, 당신은 그들이 어떤 테이블을 가리키고 있는지 확인할 필요없이 같은 것을 가리키고 있다는 것을 알고있었습니다. 동일한 열의 13은 다른 테이블의 기본 키일 수 있습니다. 나는 그 디자인 스타일에 개인적으로 매우 불편하다.
Lawtonfogle

@AaronBertrand 또는 간단한 정수 식별자를 사용하거나 고객이 직면 할 때 처음에 일부 코드를 추가하십시오. 예. I1337, C1337 송장 또는 고객 명확하게
JamesRyan

7

이 아이디어는 사람들이 실수로 잘못된 열을 사용하여 테이블에 조인하고 INT ID가 동일하기 때문에 잘못된 행을 얻을 수있는 매우 복잡한 데이터베이스에서 장점을 가지고 있습니다.

GUID의 인덱스 조각화 함정을 피하기 위해 순차 GUID를 기본 키로 선택했습니다. 슬프게도 그들은 상당히 큽니다.

SQL Server는 newSequentialID () 함수를 호출하는 기본값을 통해 순차적 GUID를 생성 할 수 있으므로 유지 관리 할 키 테이블이없고 차단 병목 현상이 없습니다.

이는 실제로 데이터베이스 전체, 회사 전체에 걸쳐 고유 한 ID를 부여했습니다.

물론 작은 크기의 정수 키를 사용하여 속도 / 크기가 지정된 데이터웨어 하우스 / 큐브로 데이터를 가져 오려고 할 때의 가격은 공간이며 문제가됩니다.

우리는 버그를 사용한 결과 앱에서 많은 버그를 피했다고 확신합니다.


4

모든 테이블에서 단일 시퀀스의 원인이 무엇인지 상상할 수 없습니다. 새 값을 생성 할 때 병목 현상이 발생하기 만하면됩니다.

순차 키 값을 생성하는 오버 헤드가 아무리 작더라도 생성기는 단일 자원이며 액세스해야하는 액세스입니다. 요청이 많을수록 일부 요청자가 탭에서 자신의 차례를 기다려야 할 가능성이 높아집니다. 모든 테이블간에 공유되는 단일 시퀀스 생성기는 더 많은 클라이언트가 더 자주 액세스하므로 여러 생성기 중 하나보다 더 많은 경합이 발생합니다. 격차 나 엄격한 순서가 없거나 클러스터 된 데이터베이스와 같이 비즈니스 규칙이 생성 된 값에 제한을 가하면 경합이 더욱 두드러 질 수 있습니다.

가장 효율적인 시퀀스 생성기라도 견딜 수없는 경합을 유발하는 워크로드 가 있습니다 .


2
병목 현상이 발생하는 방법과 그 이유가 나쁜 이유에 대한 세부 정보를 추가 할 수 있습니다.
Max Vernon

2

데이터베이스 테이블에서 PrimaryKey의 목적은 기본적으로 고유해야하는 데이터의 고유성을 적용하는 것입니다. 모든 워크 플로를 다룰 수없고 데이터 중복을 초래하지 않을 것이기 때문입니다. 두 번째 이유는 PK가 여러 번 테이블에 대한 클러스터 된 인덱스의 주요 후보이기도하므로 선택 열에서 이러한 열이 올바르게 사용되는 경우 / 데이터의 검색을 향상시키는 것입니다.

기본 키로 시퀀스 번호를 사용하는 것은 모든 테이블에 ID 열이 있고 해당 열만 PrimaryKey에서 사용되는 것과 동일합니다. DB에서 단일 시퀀스 번호를 갖는 것은 특정 사용법이 있어야하지만 PrimaryKey 관점에서 이유를 이해하지 못합니다. 예를 들어 필자가 작업 한 Datawarehouse 프로젝트 중 하나에서 LoadBatchID라는 열이 있으며 ETL에서 모든 테이블의 50 %를보고하는 데이 열이 있지만 어떤 곳에서는 다른 의미를 갖습니다. 우리는 고유 한 proc을 숫자 생성기로 사용하여 충돌을 발견하지 않았으며 데이터가 어디에서 왔는지와 ETL의 각기 다른 단계에서 발생하는 원본 파일을 다시 추적 할 수있었습니다.


2

모든 엔터티가 일부 상위 엔터티에서 상속 된 경우 한 가지 이유가 있다고 가정합니다. 예를 들어 모든 유형의 엔티티에 주석을 달고 싶다고 가정 해보십시오.

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

일반적으로이 작업은 수행되지 않습니다. .

성능 특성을 모릅니다.

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