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


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.