문자열 키 사용이 일반적으로 나쁜 생각으로 여겨지는 이유는 무엇입니까?


24

이것은 잠시 동안 나를 괴롭 혔습니다. 대부분의 경우 해시 테이블, 프로그래머, 서적 및 기사와 같은 구조에 데이터를 저장하는 경우 문자열 값으로 해당 구조의 요소를 인덱싱하는 것은 나쁜 습관으로 간주됩니다. 그러나 지금까지는 왜 나쁜 습관으로 여겨지는지 설명 할 수있는 단일 소스를 찾지 못했습니다. 프로그래밍 언어에 의존합니까? 기본 프레임 워크에서? 구현에?

도움이되는 경우 두 가지 간단한 예를 들어보십시오.

문자열 기본 키로 행이 색인되는 SQL과 유사한 테이블입니다.

키가 문자열 인 .NET 사전.


9
문자열 키를 갖는 것은 일반적으로 나쁜 생각이 아닙니다. 더 나은 키 유형을 사용할 수있는 상황에서 그러한 진술이 이루어 졌다고 생각합니다. 문자열 키가있는 .net 사전이 항상 있습니다. 이 주장의 예를 들어 줄 수 있습니까?
코드 InChaos

3
일반적으로 객체 / 행의 수명 동안 변경되지 않는 기본 키를 원합니다. 예를 들어 테이블 username의 기본 키가 users가장 좋은 아이디어는 아니며 자동 증가 ID를 선호합니다. 하지만 그 username문자열, 변경 가능한 프로퍼티 인 것은 주요 문제에만 부수적이다
CodesInChaos

데이터베이스에서 정수가 아닌 문자열을 색인화하는 방법을 고려하십시오.

@CodesInChaos 나는 대부분의 경우를 찾은 곳을 기억할 수 있기를 희망하지만 지금은 문제를 상기시키는 비트를 붙여 넣을 수 있습니다. 게임 대화를 논의하고 <key = string, value = object> 쌍으로 세계에 대한 사실을 저장하는 Valve의 GDC 슬라이드 쇼에서 나왔습니다.

2
끈은 괜찮습니다. '매직'문자열이 아닙니다. 따라서 해시 테이블을 사용할 때 코드에 알몸의 문자열이 없는지 확인하십시오. 큰 텍스트 값은 성능이 좋지 않기 때문에 키로 피해야하지만 대부분의 실제 상황에서 짧은 텍스트 문자열은 정수만큼 빠릅니다 (대용량 데이터베이스는 아님). 대체 키를 사용할 수도 있습니다. 예를 들어 기본 키는 숫자이지만 고유 한 '슬러그'또는 고유 한 문자열도 있습니다.
ipaul

답변:


17

그것은 모두 기본적으로 두 가지와 관련이 있습니다.

1) 조회 속도 (예를 들어 정수가 훨씬 더 나은 곳)

2) 인덱스 크기 (문자열 인덱스가 폭발 할 위치)

이제는 모두 요구 사항과 데이터 세트의 크기에 따라 다릅니다. 테이블이나 컬렉션에 10-20 개의 요소가 있으면 키의 유형은 관련이 없습니다. 문자열 키를 사용하더라도 매우 빠릅니다.

추신 : 귀하의 질문과 관련이 없을 수도 있지만, Guids는 데이터베이스 키에 대해서도 나쁜 것으로 간주됩니다 (16 바이트 Guid 대 4 바이트 정수). 대량의 데이터 볼륨에서 Guid는 조회 속도를 느리게합니다.


항상 그런 것은 아닙니다. 증분 GUID가 가능합니다. 인덱스는 여전히 크지 만 조회 페널티는 그리 나쁘지 않습니다.
Sam

7
실제로 그들은 괜찮습니다. 시간 디스크 IO 시간과 메모리의 값 비교 간의 관계를 살펴 봐야합니다. 디스크 액세스 시간이 메모리 비교를 압도하기 때문에 데이터베이스 성능 분석에서 실제로 중요한 것은 IO뿐입니다. 키가 GUID, 문자열 또는 정수인지 여부는 실제로 중요하지 않습니다. 인덱스 크기는 한 페이지에 맞는 인덱스 값의 수에 영향을 미치지 만 키가 4 바이트 int (충분하지 않고 클라이언트에서 생성 할 수 없음)인지 또는 16 바이트 값인지는 중요하지 않습니다. 일부 데이터베이스에서 rowId의 크기는 16 바이트 일 수 있습니다.
ipaul

9

문자열을 키로 사용하거나 더 정확하게 문자열 리터럴을 키로 사용하여 순수한 성능 / 효율성 이유를 제외하고 한 가지 더 문제가 있습니다. 오타. 사전에서 문자열 리터럴을 키로 사용하는 경우 문자열 리터럴이 키가 될 때 매우 놀랍게 설정 "ReceiverId"됩니다 "RecieverId". 키 값을 저장하도록 상수를 설정하고 사전에 액세스 할 때마다 재사용하십시오.

사소하고 명백하지만, 웹에서 놀랍도록 많은 .NET 코드 예제는 문자열 리터럴을 사용하여이 모호한 연습을 전파합니다. 코드베이스에 흩어져있는 모든 세션, ViewStates 및 QueryParams가있는 ASP.NET은 특히 유죄입니다.


사소한 IMHO가 아닙니다. 나는 또한이 열쇠의 경우 본 적이 "1""1 "같은 테이블에 있습니다.
pswg

믹스에서 대 / 소문자를 구분할 때 더욱 재미있어집니다. 나 자신을 포함하여 많은 사람들이 저것으로 직접 넘어졌습니다.
Tony Hopkinson

C #에서는 상수를 사용하는 것보다 식을 사용하는 것이 좋습니다. 이렇게하면 메소드 / 속성 등의 이름으로 문자열을 생성 할 수 있으므로 문자열 조회가 유형 안전하고 리팩터링 친화적입니다.
GoatInTheMachine

4

여기에는 많은 장단점이 있습니다. 실제로 문자열 키를 자주 사용하지만 조인을 위해 대리 보조 키를 포함하는 경우가 많습니다 (분명히 MySQL을 사용하는 경우에는 다른 방법 일 것입니다). 그러나 그렇지 않은 경우가 있습니다.

먼저 DB 가이를 잘 처리 할 수있는 기본 키로 자연 키를 선언하는 팬입니다 (예 : PostgreSQL). 이는 정규화에 도움이되고보다 명확한 데이터베이스 설계를 가능하게합니다. 서로 게이트 키를 사용하면 쉽게 연결할 수 있습니다.

일반적으로 대리 키를 추가하는 데는 두 가지 이유가 있습니다.

  1. 자연 키가 무엇인지 항상 명확하지는 않습니다. 때때로 이들은 변경되어야합니다. 조인 및 참조 무결성에 사용될 때 자연스럽고 복합적인 키를 변경하면 복잡하고 오류가 발생하기 쉽습니다.

  2. 복합 키의 조인 성능은 문제가되고 일단 자연스러운 키 경로를 따라 가면 문제가 발생합니다.

그러나 자연 키가 정의, 단일 열 및 텍스트 인 경우 일반적으로 문자열 키를 결합합니다. 그렇게하는 나의 이유는 이것이 종종 조회에서 조인을 피하기 때문입니다. 가장 일반적인 용도는 열거 형 유형의 사용 사례를 중심으로 적절한 db 디자인을 제공하는 것입니다. 대부분의 경우 일상적인 쿼리에 추가 조인이 필요 하지 않습니다 . 따라서이 경우 조인 키로 사용 되는 문자열 는 완벽합니다.

예를 들어 LedgerSMB에서는 계정 분류를 저장합니다. 이들은 문자열 참조로 식별되며 일부 다른 데이터는 계정에 영향을 줄 수있는 분류 조합에 관한 규칙을 시행하는 데 사용되는 문자열 참조와 함께 저장됩니다. 논리가 필요한 유일한 시간은 분류 세트를 저장할 때뿐이므로 문자열 키를 결합합니다.

기본값이 정수 키인 이유에 관해서는 인덱스 크기의 문제라고 생각하지 않습니다. 큰 문제는 키 관리입니다. 키는 임의적이며 수백만 개의 레코드를 처리 할 수 ​​있으므로 고유 한 문자열을 생성하는 방법이 있어야합니다. 사람들이 이것을 위해 UUID를 사용하는 경우가 있지만 UUID 충돌 가능성이 0이 아니며 수십억 개의 레코드가 저장되는 경우이 확률은 실제로 볼 수있을만큼 높아지지만 증가 된 정수 유형과의 충돌 가능성은 0입니다 정의에 의해.


정수 유형을 다시 0으로 감싸면 0이 아닙니다. 부호없는 32 비트 유형의 경우, 그것은 단지 4G 거리에 있으며,“수십억의 레코드”에 방해가됩니다…
Donal Fellows

"랩되지 않고 오류"라고 말할 수있는 db가 있으면 0입니다. 어쨌든 의사 난수 값보다 증가하는 정수로 충돌 가능성을 관리하는 것이 더 쉽습니다.
Chris Travers

1

특히 SQL과 같은 테이블에서 문자열을 키로 사용하는 경우 여러 가지 잠재적 인 문제가 있습니다. @bunny에서 언급했듯이 테이블의 인덱스는 더 커질 것이지만 테이블과의 외래 키 관계에는 더 가벼운 (정수) 식별자가 아닌 문자열을 포함하는 BOTH 테이블이 포함됩니다. . 첫 번째 테이블에 대한 참조가 더 많은 테이블이있는 경우 데이터베이스 전체에서 문자열 키가 확산됩니다.


1

그 자체로는 나쁜 생각이 아니며, 일반적으로 20/20의 가늠자로 열악한 디자인 타협을합니다. 문자열의 유연성과 범위 대 추가 비용 및 복잡성.

정수가 작업 범위를 현명하게 처리하고 많은 고가의 처리가 정수가 무엇을 나타내는 지 알 필요가 없으면 하나를 사용하십시오.


0

어떻게 든 해시 테이블에서 잘못된 데이터를 검색했습니다.

"DaytimeTelephone"또는 "EveningTelephone"을 의미 했습니까?

또는

1234567 또는 1234576을 의미 했습니까?

숫자는 기계에 대해 더 효율적이지만 , 일이 잘못 될 때마다 (그리고 그들이 할 때마다), 나는 당신과 내가 좋아하는 일에 빠지고 , 그 시점에서 몇 바이트의 저장 공간을 절약하고 몇 마이크로 초 (nano?)의 처리 시간이 매번 선명하게 사라집니다 .


1
따라서 코드에서 상수의 이름을 사용하여 마법의 숫자를 나타내는 상수 목록으로 끝납니다. 자바는 열거를 통해 더 멀리 추상화하고 이름과 서수를 갖도록합니다. 보이지 않는 매핑.
jwenting

-1

많은 트레이드 오프와 아무도 정답이 없습니다. 많은 프로그래머는 해시와 데이터베이스 작동 방식을 모르기 때문에 데이터베이스에서 문자열 키 사용을 고려하지 않습니다. 문자열 키가 매우 안정적이거나 의미가없는 (대리인) 문자열 키는 여러 상황에서 좋은 디자인 선택입니다.


2
이 답변은 다른 답변에서 아직 언급되지 않은 내용을 추가하지 않습니다.
Martijn Pieters

-2

문자열 키는 약 10-100 개의 짧은 문자열 레코드가있는 룩업 테이블과 관련하여 의미가 있습니다. 관련 데이터는 더 판독 가능하다 + 예를 들어 변경 추적 (숫자 / guid id vs. 문자열 예 : "관리자") btw, ASP.NET 멤버쉽 데이터베이스는 AspNetRoles에 문자열 키를 사용합니다.

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