SQL 데이터베이스에서 기본 키로 사용되는 문자열


178

데이터베이스와 그 작동 방식에 대한 이론에 익숙하지 않습니다. 정수보다 기본 키에 문자열을 사용하는 것이 성능 관점 (삽입 / 업데이트 / 쿼리)에서 속도가 느립니까?

답변:


191

기술적으로는 가능하지만 문자열이 기본 키로 이해되는 경우 아마도 사용해야합니다. 이것은 모두 테이블의 크기와 기본 키가 될 문자열의 길이에 달려 있습니다 (더 긴 문자열 == 비교하기 더 어렵습니다). 필자는 수백만 행이있는 테이블에 반드시 문자열을 사용하지는 않지만 작은 테이블에서 문자열을 사용하면 성능 저하의 양이 정수를 사용하여 두통을 겪을 수 있습니다 데이터와 관련하여 아무 의미도 없습니다.


11
데이터베이스에 의존하지 않습니까? 제대로 색인 된 문자열이 숫자에서 전혀 느리지 않을 것이라고 생각합니까?
Ryan Guill

2
고려해야 할 많은 변수가 있다는 데 동의합니다. (sqlserver에서) 10 대 중반에서 10 세 이상 길이의 문자열을 인덱싱 할 때도 실제 성능 문제가 발생했습니다. 예를 들어이 하드웨어를 극복해야 할 것이 있습니다.
kemiller2002

1
그럴 수 있지. 문자열이 의미가 있다면 사용해야한다는 데 동의합니다. 또한 자동 증가 필드가 작동하지 않는 데이터베이스에 GUID 또는 UUID 필드에 대한 시간이 확실히 있다고 말합니다.
Ryan Guill

7
또한 인덱스 비교를 수행 할 때 CHAR과 VARCHAR 간에는 매우 큰 차이가 있음을 기억하십시오.
Tom H

7
이 답변에 대한 의견 수는 얼마나 불완전한지를 명확하게합니다. 인덱싱 언급은 최소한의 대답 일 것입니다.
Pedro Rolo

74

문자열을 기본 키로 사용하는 또 다른 문제는 인덱스가 지속적으로 순차적으로 배치되기 때문에 새 키를 만들 때 순서 중간에있는 인덱스를 다시 정렬해야하는 경우입니다. 정수, 새 키가 색인 끝에 추가됩니다.


2
이로 인해 새 인서트에 "핫스팟"이 발생할 수 있습니다. 데이터베이스를 올바르게 관리하는 한 삽입 할 수 있도록 여분의 공간이 페이지에 있어야하며 페이지 분할은 드 물어야합니다.
Tom H

20
기본 키가 클러스터 된 경우입니다. 클러스터되지 않은 상태로 만들 수도 있습니다.
학습

xid 문자열 만 사용하면 도움이 될 수있는 XID가 주문됩니다
Sinaesthetic

22

시퀀스 중간에 삽입이 발생하는 클러스터형 인덱스가있는 테이블에 삽입하면 인덱스를 다시 쓰지 않습니다. 데이터를 구성하는 페이지를 다시 쓰지 않습니다. 행이 이동할 페이지에 공간이 있으면 해당 페이지에 배치됩니다. 단일 페이지가 재구성되어 페이지의 올바른 위치에 행이 배치됩니다. 페이지가 가득 차면 페이지의 행 절반이 한 페이지로 이동하고 절반이 다른 페이지로 이동하여 페이지 분할이 발생합니다. 그런 다음 페이지는 클러스터형 인덱스가있는 테이블 데이터를 구성하는 연결된 페이지 목록으로 다시 연결됩니다. 기껏해야 2 페이지의 데이터베이스를 작성하게됩니다.


좋은 설명입니다. 그러나 이것이 모든 SQL 데이터베이스에 적용됩니까? 임의의 UUID를 기본 키로 사용할 때 MySQL 성능 문제에 대해 들었습니다.
hgoebl

13

문자열은 조인 속도가 느리고 실제 생활에서는 매우 독특하지 않습니다 (심지어 있어야 할 때조차도). 유일한 장점은 이름을 얻기 위해 기본 테이블에 조인하는 경우 조인 수를 줄일 수 있다는 것입니다. 그러나 문자열도 종종 변경 될 수 있으므로 회사 이름이 변경되거나 결혼 할 때 모든 관련 레코드를 수정해야하는 문제가 발생합니다. 이것은 큰 성능 저하가 될 수 있으며 어떻게 든 관련되어야하는 모든 테이블이 관련이없는 경우 (이것이 생각보다 자주 발생하는 경우) 데이터가 일치하지 않을 수 있습니다. 레코드 수명 동안 변경되지 않는 정수는 성능 관점뿐만 아니라 데이터 무결성 관점에서 훨씬 안전한 선택입니다. 자연 키는 일반적으로 데이터 유지 관리에 적합하지 않습니다.

또한 두 세계의 최고 점은 종종 자동 증가 키 (또는 일부 특수한 경우 GUID)를 PK로 사용하고 자연 키에 고유 인덱스를 넣는 것입니다. 더 빠른 조인을 얻거나 중복 레코드를 얻지 않으며 회사 이름이 변경되어 백만 개의 하위 레코드를 업데이트 할 필요가 없습니다.


26
PK에 적합한 후보 인 문자열에는 중복이 없습니다. 그렇지 않으면 PK에 적합한 후보가 아닙니다. ICD-9 코드, 국가 코드, VIN #을 생각하십시오. 자연 키 문제의 예로 이름을 사용하는 것은 처음에는 후보자가되어서는 안되므로 잘못 안내됩니다.
Tom H

6
@Tom H : ISO 카운티 코드는 변경되지 않습니다. [ en.wikipedia.org/wiki/ISO_3166-1#Editions_and_changes ] 관련 질문에 대한 답변으로 [ stackoverflow.com/questions/925266/… ] "기본 키의 경우 고유 키를 제어 할 수 있는지 확인하십시오"
Steve Schnepp

4
@SteveSchnepp : 예. ISO는 해당 변경 관리를위한 신뢰할 수있는 기관입니다. 다른 사람의와 정수 값을 증가 당신의 단조 순서를 병합 할 때 다른 한편으로, 당신은 당신의 자신에있는)
onedaywhen

1
나는 이름이 중요한 것으로 간주되지 않는다는 것에 동의 할 것이다.
HLGEM

1
증분 정수의 2 개의 단조 시퀀스를 병합 할 때 접두사 또는 접미사를 통해 쉽게 수행 할 수 있습니다 :)
Steve Schnepp

6

고유 한 경우 기본 키로 사용하는 것은 중요하지 않습니다. 속도 나 우수한 데이터베이스 설계에 관심이있는 경우 데이터 복제를 계획하지 않는 한 int를 사용하고 GUID를 사용하십시오.

이것이 액세스 데이터베이스이거나 작은 응용 프로그램이라면 누가 정말로 관심을 갖습니다. 나는 우리 대부분의 개발자들이 오래된 int 또는 guid를 앞쪽으로 때리는 이유는 프로젝트가 우리를 성장시키는 방법을 가지고 있기 때문에 자신에게 성장 옵션을 남기고 싶어하기 때문이라고 생각합니다.


5

변수가 너무 많습니다. 그것은 테이블의 크기, 인덱스, 문자열 키 도메인의 특성에 달려 있습니다 ...

일반적으로 정수가 빠릅니다. 그러나 차이가 충분히 커질 것입니까? 말하기 어렵다.

또한 문자열을 선택하려는 동기는 무엇입니까? 숫자 자동 증가 키도 종종 훨씬 쉽습니다 . 의미론인가? 편의? 복제 / 연결 끊김 문제? 귀하의 답변이 옵션을 제한 할 수 있습니다. 이것은 또한 당신이 잊고있는 세 번째 "하이브리드"옵션을 떠올리게합니다 : Guids.


그건 말도 안되는 말이니 무슨 말이야?
HLGEM

@ HLGEM : 필자가 글을 이해하면 랩톱에서 만든 레코드를 기본 DB와 동기화하는 것을 의미합니다.
Joel Coehoorn

동일한 엔터티를 가진 두 개의 개별 데이터베이스가 있으며 영구 스토리지 목적으로 하나만 업데이트되는 빈도가 적습니다. 데이터베이스 A에서 "캘리포니아"엔터티를 쿼리하는 경우 데이터베이스 B에서 기본적으로 동일한 "캘리포니아"가
되기를 원합니다

1
또한 같은 문제라는 점에서 랩톱에서 만든 레코드를 '같은'동기화합니다. 한 곳에서 만든 레코드가 다른 곳에서 만든 레코드와 충돌하지 않아야합니다. 가능한 해결책 중 하나는 Guid 키입니다.
Joel Coehoorn

5

데이터가 설명하고 데이터의 의도 된 용도에 잘 맞는 주제와 일치하는 단순하고 건전한 디자인을 얻을 때까지 성능에 대해 걱정하지 마십시오. 그런 다음 성능 문제가 발생하면 시스템을 조정하여 문제를 해결할 수 있습니다.

이 경우 문자열을 자연스러운 기본 키로 사용하고 신뢰할 수 있다면 거의 항상 더 좋습니다. 문자열이 합리적으로 짧으면 최대 25 자 정도라고 문자열을 걱정하지 마십시오. 성능면에서 큰 가격을 지불하지 않습니다.

데이터 입력 사용자 또는 자동 데이터 소스가 항상 가정 된 자연 키에 대한 값을 제공합니까, 아니면 생략합니까? 입력 데이터에서 때때로 잘못 되었습니까? 그렇다면 오류는 어떻게 감지되고 수정됩니까?

쿼리를 지정하는 프로그래머와 대화식 사용자는 자연 키를 사용하여 원하는 것을 얻을 수 있습니까?

자연 키를 신뢰할 수 없으면 대리를 발명하십시오. 대리를 발명하면 정수도 발명 할 수 있습니다. 그런 다음 사용자 커뮤니티에서 대리를 숨길 것인지에 대해 걱정해야합니다. 대리 키를 숨기지 않은 일부 개발자는 후회했습니다.


3

지수는 많은 비교를 의미합니다.

일반적으로 문자열은 정수보다 길고 데이터 정렬 규칙을 비교에 적용 할 수 있으므로 문자열 비교는 일반적으로 정수를 비교하는 것보다 계산 집약적 인 작업입니다.

그러나 때로는 string to numerical id테이블 과의 추가 조인을 수행하는 것보다 문자열을 기본 키로 사용하는 것이 더 빠릅니다 .


2

예.하지만 수백만 행을 기대하지 않는 한 문자열 기반 키를 사용하지 않으면 일반적으로 "초기 최적화"가 느려집니다. 결국 문자열은 큰 숫자로 저장되고 숫자 키는 일반적으로 작은 숫자로 저장됩니다.

그러나주의해야 할 사항은 임의의 키에 인덱스를 클러스터하고 인덱스에서 비 순차적 인 많은 수의 삽입을 수행하는 경우입니다. 기록 된 모든 줄은 인덱스를 다시 쓰게합니다. 배치 삽입을 수행하는 경우 프로세스 속도가 느려질 수 있습니다.


2

PK 열에 정수를 사용해야하는 두 가지 이유 :

  1. 자동 증분 된 정수 필드의 아이덴티티를 설정할 수 있습니다.

  2. PK를 만들 때 db는 테이블에 저장되기 전에 데이터를 정렬하는 인덱스 (Cluster 또는 Non Cluster)를 만듭니다. PK에서 ID를 사용하면 옵티마이 저는 레코드를 저장하기 전에 정렬 순서를 확인할 필요가 없습니다. 이는 큰 테이블의 성능을 향상시킵니다.


1

문자열을 기본 키로 사용하는 이유는 무엇입니까?

기본 키를 자동 증분 정수 필드로 설정하고 문자열 필드에 색인을 넣습니다.

이렇게하면 테이블에서 검색을 수행하면 비교적 빠르며 모든 조인 및 일반 조회는 속도에 영향을 미치지 않습니다.

인덱싱되는 문자열 필드의 양을 제어 할 수도 있습니다. 다시 말해, 충분하다고 생각되면 "처음 5 자만 색인화"라고 말할 수 있습니다. 또는 데이터가 비교적 유사 할 수있는 경우 전체 필드를 색인화 할 수 있습니다.


3
지능을 키에 넣는 것은 문제를 요구한다고 생각합니다. 그들은 독특하게 유지됩니까? 그들은 고객 이동으로 시작할 때 주 약어를 사용하여 모든 계좌 번호를 시작 했습니까? 계정 번호로 연결된 모든 테이블을 문제없이 업데이트하십시오.
JeffO

1
문자열을 PK로 사용하는 예는 설정 테이블 일 수 있습니다. 예를 들어 settingNamePK, isUserEditable, isCustomerEditable 등. 그런 다음 설정 동작을 수정하려면 "UPDATE setting SET ... WHERE settingNamePK = 'dailyWorkObligation'"이 ID를 사용하고 ID 매핑을 어딘가에 저장하는 것보다 훨씬 좋습니다. 물론 정수 PK를 가질 수 있고 설정 이름을 다른 고유 키로 지정할 수도 있습니다.
MeatPopsicle

기본 키가 자동 증분 정수인 경우 인서트도 속도에 영향을 미치지 않아야합니까?
Dennis

흥미로운 Rails 개발자 를 위해 색인 길이를 지정하는 방법은 다음 과 같습니다 . SQLite는 인덱스 길이를 지원하지 않습니다.
Dennis

1

성능 관점에서-예 문자열 (PK)은 정수 (PK)를 사용하여 달성 한 성능과 비교할 때 성능을 느리게합니다. 여기서 PK ---> 기본 키.

요구 사항 관점에서-이것은 여전히 ​​귀하의 질문의 일부는 아니지만 언급하고 싶습니다. 여러 테이블에서 거대한 데이터를 처리 할 때 일반적으로 특정 테이블에 설정할 수있는 가능한 키 집합을 찾습니다. 이것은 주로 많은 테이블이 있고 주로 각 또는 일부 테이블이 어떤 관계 (외래 키 개념)를 통해 다른 테이블과 관련되기 때문입니다. 따라서 항상 정수를 기본 키로 선택할 수는 없지만 3, 4 또는 5 속성을 해당 테이블의 기본 키로 조합해야합니다. 레코드를 다른 테이블과 관련시킬 때 해당 키를 외래 키로 사용할 수 있습니다. 이것은 필요할 때 다른 테이블에 레코드를 관련시키는 데 유용합니다.

따라서 최적의 사용을 위해-항상 1 또는 2 개의 문자열 속성으로 1 또는 2 개의 정수를 조합하지만 필요한 경우에만 다시 조합합니다.


0

데이터베이스의 문자열과 관련된 매우 큰 오해가있을 수 있습니다. 거의 모든 사람들이 숫자의 데이터베이스 표현이 문자열보다 더 간결하다고 생각했습니다. 그들은 db-s에서 숫자는 메모리에서와 같이 표현된다고 생각합니다. 그러나 사실이 아닙니다. 대부분의 경우 숫자 표현은 다른 표현과 유사한 문자열에 더 가깝습니다.

숫자 또는 문자열을 사용하는 속도는 유형 자체보다 색인 작성에 더 의존합니다.


0

기본적으로 ASPNetUserIds는 128 자 문자열이며 성능은 괜찮습니다.

키가있는 경우 HAS 테이블에서 고유하기는 키해야합니다. 이유는 다음과 같습니다.

기본 문자열 키 = 올바른 DB 관계, 1 문자열 키 (기본) 및 1 문자열 인덱스 (기본).

다른 옵션은 일반적인 INT 키이지만, 문자열이 경우 HAS 고유해야합니다 당신은 아마 아직도 유효한지 확인할 수 있기 때문에 논스톱 쿼리의 인덱스를 추가하거나 독특한 있는지 확인해야합니다.

따라서 int identity key = 잘못된 DB 관계, 1 int key (Primary), 1 int index (Primary), 아마도 고유 문자열 Index를 사용하고 동일한 문자열을 수동으로 유효성 검사 해야하는 것은 존재하지 않습니다 (sql 확인과 같은 것) ).

기본 키에 대한 문자열을 통해 int를 사용하여 더 나은 성능을 얻으려면, 문자열이 때 HAS 고유해야합니다, 그것은 매우 이상한 상황이 될 것이다. 나는 항상 문자열 키를 사용하는 것을 선호했습니다. 당신이 때까지 그리고 엄지 손가락의 좋은 규칙으로, 데이터베이스를 비정규하지 않는 필요해 에.

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