항상 단일 정수 열을 기본 키로 사용하는 단점은 무엇입니까?


18

내가 작업하는 하나의 웹 응용 프로그램 내에서 모든 데이터베이스 작업은 Entity Framework ORM에 정의 된 일부 일반 리포지토리를 사용하여 추상화됩니다.

그러나 일반 리포지토리를 단순하게 디자인하려면 관련된 모든 테이블이 고유 정수 ( Int32C #, intSQL)를 정의해야합니다 . 지금까지는 항상 테이블의 PK였으며 또한 IDENTITY.

외래 키가 많이 사용되며 이러한 정수 열을 참조합니다. 일관성과 ORM에 의한 탐색 특성 생성에 필요합니다.

응용 프로그램 계층은 일반적으로 다음 작업을 수행합니다.

  • 테이블에서 초기 데이터로드 (*)-SELECT * FROM table
  • 업데이트 -UPDATE table SET Col1 = Val1 WHERE Id = IdVal
  • 삭제 -DELETE FROM table WHERE Id = IdVal
  • 삽입 -INSERT INTO table (cols) VALUES (...)

덜 빈번한 작업 :

  • 대량 삽입 - BULK INSERT ... into table생성 된 식별자를 검색하기 위해 모든 데이터로드가 뒤 따름 (*)
  • 대량 삭제 -이것은 일반적인 삭제 작업이지만 ORM의 관점에서 "대량"입니다.DELETE FROM table where OtherThanIdCol = SomeValue
  • 대량 업데이트 -이것은 일반적인 업데이트 작업이지만 ORM의 관점에서 볼 때 "대량"입니다.UPDATE table SET SomeCol = SomeVal WHERE OtherThanIdCol = OtherValue

* 모든 작은 테이블은 응용 프로그램 수준에서 캐시되며 거의 모든 SELECTs데이터베이스에 도달하지 않습니다. 전형적인 패턴은 초기 하중과 많은 INSERTs, UPDATEs 및 DELETEs입니다.

현재 응용 프로그램 사용을 기반으로 테이블에서 100M 레코드에 도달 할 가능성은 매우 적습니다.

질문 : DBA의 관점에서이 테이블 디자인 제한으로 인해 심각한 문제가 발생할 수 있습니까?

[편집하다]

답변 (훌륭한 피드백 감사)과 참조 기사를 읽은 후에 더 자세한 내용을 추가해야한다고 생각합니다.

  1. 현재 응용 프로그램 사양 -모델을 다른 응용 프로그램에서도 재사용 할 수 있는지 이해하고 싶기 때문에 현재 웹 응용 프로그램에 대해서는 언급하지 않았습니다. 그러나 필자의 특별한 경우는 DWH에서 많은 메타 데이터를 추출하는 응용 프로그램입니다. 소스 데이터가 매우 지저분하고 (이상한 방식으로 비정규 화되어 일부 불일치가 발생하고 많은 경우 자연 식별자가 없음) 내 앱이 명확하게 분리 된 엔티티를 생성합니다. 또한 생성 된 많은 식별자 ( IDENTITY)가 표시되므로 사용자가이를 비즈니스 키로 사용할 수 있습니다. 대규모 코드 리팩토링 외에도 GUID 사용을 제외합니다 .

  2. "행을 고유하게 식별 할 수있는 유일한 방법이되어서는 안됩니다" (Aaron Bertrand ♦)-이는 매우 좋은 조언입니다. 내 모든 테이블은 비즈니스 중복이 허용되지 않도록 UNIQUE CONSTRAINT도 정의합니다.

  3. 프런트 엔드 앱 중심 디자인과 데이터베이스 중심 디자인 -디자인 선택은 이러한 요인에 의해 발생합니다

    1. Entity Framework 제한 사항 -여러 열 PK가 허용되지만 해당 값을 업데이트 할 수 없습니다

    2. 사용자 지정 제한 -단일 정수 키를 사용하면 데이터 구조와 비 SQL 코드가 크게 단순화됩니다. 예 : 모든 값 목록에는 정수 키와 표시된 값이 있습니다. 더 중요한 것은 캐싱으로 표시된 모든 테이블이 Unique int key -> value맵 에 배치 될 수 있음을 보장합니다 .

  4. 복잡한 선택 쿼리 -모든 작은 (<20-30K 레코드) 테이블 데이터가 응용 프로그램 수준에서 캐시되므로 거의 발생하지 않습니다. 이로 인해 애플리케이션 코드를 작성할 때 (LINQ를 작성하기가 더 어려워) 인생이 조금 어려워 지지만 데이터베이스는 훨씬 더 훌륭합니다.

    1. 목록보기 - SELECT로드시 (모든 것이 캐시 됨) 또는 다음과 같은 쿼리를 생성하지 않습니다 .

      SELECT allcolumns FROM BigTable WHERE filter1 IN (val1, val2) AND filter2 IN (val11, val12)

      다른 모든 필수 값은 캐시 조회 (O (1))를 통해 페치되므로 복잡한 쿼리가 생성되지 않습니다.

    2. 뷰 편집 - SELECT다음과 같은 명령문 이 생성됩니다 .

      SELECT allcolumns FROM BigTable WHERE PKId = value1

(모든 필터와 값은 ints입니다)


시스템 생성 대리 값이있는 열 사용과 관련하여 일부 논리적, 물리적 및 실제적인 측면이 논의되므로 이러한 관련성있는 게시물 을 찾을 수 있습니다 .
MDCCL

답변:


19

추가 디스크 공간 (및 차례로 메모리 사용 및 I / O) 외에, 필요하지 않은 테이블 (IDENTITY 열이 필요하지 않은 테이블의 예)에도 IDENTITY 열을 추가해도 아무런 가 없습니다 사용자를 자신의 권한에 매핑하는 것과 같은 간단한 접합 테이블입니다.

나는 2010 년부터 블로그 게시물의 모든 단일 테이블 에 맹목적으로 추가하는 것에 반대합니다 .

그러나 대리 키에는 유효한 유스 케이스가 있습니다. 고유성을 보장한다고 가정하지 않도록주의하십시오 (때로는 추가되는 이유- 행을 고유하게 식별하는 유일한 방법 이 아니어야 함 ). ORM 프레임 워크를 사용해야하고 실제 키가 정수가 아니거나 단일 열이 아니거나 하나도 아닌 경우에도 ORM 프레임 워크에 단일 열 정수 키가 필요한 경우 고유 제한 조건 / 인덱스를 정의해야합니다. 진짜 열쇠도.


빠른 답변 감사합니다. 예, 응용 프로그램은 ORM (EF)을 사용합니다. 단일 정수 열 키가 필요하지 않지만 일반적인 제한 작업을 훨씬 쉽게 (디자인 방식으로) 만들기 위해이 제한을 도입했습니다. 또한 모든 응용 프로그램 캐시는 키별로 빠른 검색을 위해 맵 (사전)에 모든 것을 저장하며 키는 고유해야합니다. guid에 대해 정수를 선택 했으므로 삽입하는 테이블에 IDENTITY를 사용해야합니다. 고정 값 테이블의 경우 IDENTITY가 필요하지 않습니다.
Alexei

자연 키의 고유성 검사를 피해야하는 경우가 있다고 생각합니다. GIS 데이터로 작업하는 사람으로서, 즉시 염두에 두어야 할 것은 자연 키가 지오메트리 자체이거나 지오메트리에 외래 키가있는 위치입니다. 정확한 지오메트리로 물건을 찾는 것은 항상 비현실적이므로 그에 대한 고유성 제약은 많은 도움이되지 않으며 성능 저하가 발생할 수 있습니다. 자연 키의 일부가 긴 텍스트 열인 경우에도 마찬가지입니다. 그러나 동의합니다. 가능할 때마다 자연 키에 대한 고유 한 제약 조건을 적용해야합니다.
jpmc26

13

내 경험상 모든 테이블에 대해 별도의 ID를 사용해야하는 주된 이유는 다음과 같습니다.

거의 모든 경우에 내 고객 은 개념 단계에서 일부 외부 "천연"필드 가 영원히 고유하게 유지되며 주어진 엔티티에 대해 절대 변경되지 않으며 재사용되지 않을 것이라는 선 서서를 맹세 했습니다 XYZBLARGH_ID. 기본 키 속성이 손상되었습니다. 그것은 그런 식으로 작동하지 않습니다.

그런 다음 DBA의 관점에서 DB를 느리게하거나 부풀게 만드는 것은 확실히 행당 4 바이트가 아니거나 인덱스가 잘못되거나 누락 된 것, 테이블 / 인덱스 재구성을 잊어 버린 것, 잘못된 RAM / 테이블 스페이스 튜닝 매개 변수와 같은 것입니다. , 바인드 변수 사용 등을 무시합니다. 그것들 은 추가 ID 열이 아닌 10, 100, 10000의 요인으로 DB를 느리게 할 수 있습니다.

따라서 행당 32 비트가 추가로 기술적으로 측정 가능한 단점이 있더라도 ID를 최적화 할 수 있는지 여부가 아니라 특정 시점에서 ID가 필수적 인지 여부는 문제가되지 않습니다. 아마 아닙니다. 그리고 ORM 예제와 같은 소프트웨어 개발 자세의 모든 "부드러운"혜택이나 설계상의 모든 ID가 동일한 데이터 유형 등을 가질 때 소프트웨어 개발자가 더 쉬워진다는 사실을 무시하지는 않겠습니다. .

주의 : n:m연관 테이블에 대해 별도의 ID가 필요하지 않습니다. 이러한 테이블의 경우 연관된 엔티티의 ID가 기본 키를 형성해야하기 때문입니다. 이에 대한 반례는 기괴한 이유가 무엇이든 동일한 두 엔티티n:m 간 다중 연관을 허용 하는 이상한 연관입니다 . PK를 작성하려면 고유 ID 열이 필요합니다. 이 있습니다 그들은 이러한 라이브러리 작업을해야하는 경우 즉, 개발자들과 관대 될 수있는 이유가 될 것이다, 그래서하지만 다중 열 PK와를 처리 할 수 ORM 라이브러리.


2
"동일한 두 엔티티 사이에 여러 개의 연관을 허용하는 이상한 n : m 연관"현실에서 매우 일반적입니다. 예를 들어, 사람이 자동차를 소유 한 경우 소유권이 시작되고 종료 될 때 요구 사항이 점수로 변경됩니다 (사람이 자동차를 판매 한 다음 나중에 다시 구매하여 소프트웨어를 충돌시킬 수 있습니다 ....)
Ian Ringrose

예, @IanRingrose와 같은 것입니다.
AnoE

6

모든 테이블에 무의미한 추가 열을 추가하고 해당 열만 외래 키로 참조하는 경우 필연적으로 데이터베이스를 더 복잡하고 사용하기 어렵게 만듭니다. 효과적으로 외래 키 속성에서 사용자에게 관심있는 데이터를 제거하고 동일한 정보를 검색하기 위해 사용자 / 응용 프로그램이 추가 조인을 수행하도록 강제 할 것입니다. 쿼리가 더 복잡해지고 옵티마이 저의 작업이 어려워지고 성능이 저하 될 수 있습니다.

테이블은 그렇지 않은 경우보다 "실제"데이터로 더 적게 채워집니다. 따라서 데이터베이스를 이해하고 확인하기가 더 어려워집니다. 또한 특정 유용한 제약 조건을 적용하는 것이 어렵거나 불가능하다는 것을 알 수 있습니다 (제약 조건에는 더 이상 동일한 테이블에없는 여러 특성이 포함됨).

키를 더 신중하게 선택하고 이유가있을 때만 정수로 만들 것을 제안합니다. 독단적 인 규칙에 의존하기보다는 우수한 분석, 데이터 무결성, 실용성 및 검증 가능한 결과를 기반으로 데이터베이스 설계를 수행하십시오.


1
그러나 많은 시스템은 이러한 문제를 겪지 않고 모든 테이블 (예 : 거의 모든 Ruby on Rails 앱에서 작성)에 합성 정수 기본 키를 가지고 있습니다. 또한 모든 외래 키 테이블에 대한 기본 키 변경 사항을 발생시키지 않아야하는 문제로 인해 어려움을 겪지 않습니다.
David Aldridge

2
이 질문은 가능한 단점을 물었으므로 대답했습니다. 현명하게 사용하면 서로 게이트 키가 의미가 있다는 것을 부정하지 않습니다. 그러나 3,4,5 (또는 그 이상) 의미없는 외래 키가있는 테이블을 보았으므로 유용한 결과를 얻으려면 3,4,5 이상의 조인이 필요했습니다. 보다 실용적인 디자인은 조인이 전혀 필요하지 않았을 수 있습니다.
nvogel

1
나는 사람들이 그러한 디자인에있어 가장 큰 문제인 그러한 쿼리의 실행이라고 확신하지 못한다. 그것은 종종 그들이 반대하는 쿼리를 작성하는 것이다.
David Aldridge

5

다양한 데이터베이스에 대한 경험에서 Integer 기본 키는 키가 전혀 정의되지 않은 응용 프로그램보다 항상 좋습니다 . 또는 논리적이지 않은 어색한 방법으로 십여 개의 varchar 열을 결합하는 키가 있습니다 ... (한숨)

정수 PK에서 GUID로 전환 한 응용 프로그램을 보았습니다. 그 이유는 특정 경우에 여러 소스 데이터베이스의 데이터를 병합해야했기 때문입니다. 개발자는 모든 키를 GUID 로 전환 하여 병합의 일부가 아닌 테이블 (데이터가 미래 병합의 일부가되었을 경우)에서도 데이터 충돌에 대한 두려움없이 병합이 발생할 수 있도록했습니다.

별도의 소스에서 데이터를 병합하거나 정수 크기 제한을 초과하는 데이터가있을 수 없다면 정수 PK는 당신을 물지 않을 것이라고 말하고 싶습니다. 삽입을위한 공간이 부족할 때까지 모든 재미와 게임입니다 .

나는 것을,하지만 말할 것입니다 수있는 테이블이 더 자주 방식이 조회 될 경우, 감각이 당신의 PK가 아닌 다른 컬럼에 클러스터 된 인덱스를 설정 할 수 있습니다. 그러나 특히 대량의 업데이트 및 선택이 PK 값을 기반으로하는 경우에는 예외입니다.


2
모든 키를 안내 자로 바꾸는 것은 끔찍한 정당화처럼 들립니다. 나는 현재 모든 대리 키에 guid를 사용하는 데이터베이스로 작업하고 있습니다. 재미는 없습니다.
Andy

2
아니요. GUID 사용은 재미 있지 않습니다. 나는 그것들을 좋아하지 않지만 특정 사용 사례에서 그들의 가치를 존중합니다.
CaM

2

따로두기 :

  • 종교 전쟁 (Google 대리 대 자연 키)
  • 테이블에서 정의 할 클러스터형 인덱스의 별도 문제
  • 모든 데이터를 캐싱 할 수있는 가능성

적절한 곳에서 대량 삭제 / 업데이트를 사용하고 이러한 작업을 지원하기위한 인덱스가 있다면 사용하는 PK 표준으로 인해 문제가 발생하지 않을 것입니다.
나중에 EF가 조인 등을 사용하여 쿼리를 생성하는 경우 자연 키 기반 리포지토리보다 효율적이지 않을 수는 있지만 그 영역에 대해 확실하게 알 수는 없습니다.


4
자연 키의 조인이 정수의 조인보다 효율적인 단일 사례를 생각할 수 없습니다. 많은 자연 키가 4 바이트보다 작을 수 없으며, 고유 키가 충분하지 않은 경우 차이 재료를 만들기 위해 행.
Aaron Bertrand

유능하고 최적화 가능한 SQL의 경우 동의하지만 SQL 생성기의 가능한 제한 사항을 언급했습니다. .net 개발자가 EF에 대해 충분히 알지 못했거나 다른 이유가있을 수 있지만,이 분야에서 저의 유일한 경험은 EF를 숟가락으로 공급할 수있는 광범위한 견해를 만들어야한다는 것입니다.
TH

@AaronBertrand 나는 그들이 더 효율적일 수있는 유일한 방법은 조인이 전혀 필요하지 않은 경우라고 말합니다. 자연 키 사용을 고려하는 유일한 장소는 ISO4127 통화 코드 (인간이 인식 할 수있는)와 같은 표준 코드 목록을 사용하는 것 뿐이며 GBP, EUR 등을 통화 코드의 기본 또는 대체 키에 대한 외래 키로 사용할 수 있습니다 표.
David Aldridge 17

@David 물론, 조인이 필요한 경우에 대해 이야기하고있었습니다. 자연 키가 변경 될 수 있기 때문에 모든 관련 테이블에서 자연 키가 확산되는 것을 원하지 않는 많은 경우가 있습니다. 이는 고통스러운 일입니다.
Aaron Bertrand

흠, 나는 내 대답이 대리에 대해 자연 외래 키를 홍보하는 것으로 어떻게 오해 될 수 있는지 봅니다. 분명히 a) Alexei의 질문을 "자연 키를 사용하지 않는 것이 문제입니까?"로 읽었으므로 b) Alexei의 마무리 질문은 "DBA의 관점에서"로 시작했기 때문에 실제로 언급했습니다. 나는 하나 이상의 관점이 있다는 것을 인정해야한다고 생각했다. 나는 대리 외래 키 캠프에 굳게 서있다.
TH

2

안내에 도움이되는 몇 가지 요소가 있습니다.

  1. 정의 및 사양.

    작업이나 물리 법칙에 의해 고유 한 것으로 정의 된 경우 대리 키로 시간을 낭비하고 있습니다.

  2. 독창성.

    개인 위생, 조인 및 고급 데이터베이스 기능을 위해서는 (a) 고유 열, (b) 고유 열 시리즈가 필요합니다.

    충분히 정규화 된 스키마 (1NF)는 다음 중 하나를 제공합니다. 그렇지 않은 경우 항상 생성 해야합니다 . 일요일에 자원 봉사자로 설정된 사람들의 명단에 성 및 이름이 포함 된 경우, Joe Bob이 두 명있을 때 알고 싶을 것입니다.

  3. 구현 및 최적화.

    int는 비교 및 ​​평등이 빠른 작은 데이터 형식 인 경향이 있습니다. 데이터 정렬이 로캘 (위치 및 언어)에 따라 달라질 수있는 유니 코드 문자열과 비교하십시오. ASCII / UTF8 문자열에 4242를 저장하는 것은 4 바이트입니다. 정수로 저장하면 2 바이트에 맞습니다.

따라서 단점이 있다면 몇 가지 요소가 있습니다.

  1. 혼란과 모호함.

    1. @Aaron Bertrand 블로그 항목은 이것을 잘 요약합니다. 사양과 작업에 의해 OrderID 를 갖고 데이터베이스 구현을 통해 " OrderID " 를 부과하는 것은 자체 문서화가 아닙니다 . 때로는이를 명확히하거나 규칙을 작성해야하지만 혼란을 야기 할 수 있습니다.
  2. 우주.

    정수는 여전히 행에 공간을 추가합니다. 그리고 당신이 그들을 사용하지 않으면 목적이 없습니다.

  3. 클러스터링.

    한 방향으로 만 데이터를 주문할 수 있습니다. 필요하지 않은 대리 키를 적용하는 경우 해당 방식 또는 자연 키 방식을 클러스터링합니까?


좋고 짧은 장단점.
Alexei

@Alexei 고마워요, 당신이 찾고있는 것을 충족시키는 경우 선택된 것으로 표시하는 것을 고려하십시오. 또는 설명을 요구합니다.
Evan Carroll
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.