INT와 VARCHAR 기본 키간에 실제 성능 차이가 있습니까?


174

MySQL에서 INT와 VARCHAR을 기본 키로 사용하는 것 사이에 측정 가능한 성능 차이가 있습니까? VARCHAR을 참조 목록의 기본 키 (미국, 국가 코드)로 사용하고 싶을 때 동료가 INT AUTO_INCREMENT를 모든 테이블의 기본 키로 버리지 않습니다.

여기 에 설명 된 바와 같이 , INT와 VARCHAR의 성능 차이는 무시할 만하다는 나의 주장 은 모든 INT 외래 키 참조가 참조를 이해하기 위해 JOIN을 필요로하기 때문에 VARCHAR 키는 정보를 직접 제공합니다.

그렇다면 누구나이 특정 사용 사례 및 이와 관련된 성능 문제에 대한 경험이 있습니까?


3
나는 내가 실행 한 테스트의 세부 사항과 함께 "아니오"라는 답변을 게시했습니다 ...하지만 그것은 MySQL이 아닌 SQL Server였습니다. 그래서 나는 대답을 삭제했다.
Timothy Khouri

17
@Timothy-삭제하지 않아야합니다. 나는 그것을 투표하는 과정에 있었다. 대부분의 SQL 데이터베이스 서버에는 유사한 쿼리 플래너 및 유사한 성능 병목 현상이 있습니다.
Paul Tomblin

9
@Timothy는 결과를 다시 게시하십시오.
Jake McGraw

2
많은 의견과 답변은 키가 조인에 사용된다고 가정합니다. 그들은 아닙니다. 중복 행을 피하기 위해 데이터 일관성을 위해 키가 사용됩니다 (동일한 엔티티를 나타내는 둘 이상의 행). 모든 열 (또는 열 집합)을 조인에 사용할 수 있으며 조인이 일대일 또는 많은 열임을 보장하기 위해 단순히 고유해야합니다. 고유 인덱스는이를 보장하며 의미가 없습니다.
Charles Bretana

답변:


78

대리 키 대신 자연 키 를 사용하여 몇 개의 조인 된 쿼리를 피할 수 있다는 것이 좋습니다 . 응용 프로그램에서이 기능의 이점이 중요한지 여부 만 평가할 수 있습니다.

즉, 애플리케이션에서 대량의 데이터를 처리하거나 매우 자주 실행되기 때문에 가장 빠른 쿼리를 측정 할 수 있습니다. 이러한 쿼리가 조인을 제거하여 이익을 얻지 만 varchar 기본 키를 사용해도 문제가되지 않으면 수행하십시오.

데이터베이스의 모든 테이블에 전략을 사용하지 마십시오. 경우에 따라 자연 키가 더 좋을 수도 있지만 대리 키가 더 좋을 수도 있습니다.

다른 사람들은 자연 키가 절대로 변경되거나 복제되지 않는 것이 실제로 드물다는 점을 지적하므로 대체 키는 일반적으로 가치가 있습니다.


3
그리고 때때로, (이럴 종종), 모두가 더 나은 다른 테이블에서 FK 참조에 사용하는 대리이며, 대한 조인 및 자연 키 데이터 일관성을 보장하기 위해
찰스 Bretana

@CharlesBretana 흥미 롭습니다. FK 측면에서 데이터 일관성을 위해 자연 키를 사용하는 것이 일반적인 관행입니까? 내 첫 번째 생각은 큰 테이블에 필요한 여분의 스토리지가 가치가 없을 수도 있다는 것입니다. 모든 정보를 부탁드립니다. 참고로-괜찮은 프로그래밍 배경을 가지고 있지만 SQL 경험은 주로 SELECT 쿼리로 제한됩니다.
Rob

2
@CharlesBretana "모두 저장"을 읽을 때 "이중화"및 "정규화되지 않음"은 "이것은 망칠 수 있습니다"및 "하나라도 변경되면 둘 다 변경해야합니다"와 같습니다. 중복성이있는 경우 중복성이 항상 데이터가 일치하지 않을 가능성이 있기 때문에 완전히 수용 할 수없는 성능과 같은 매우 좋은 이유가 있습니다.
jpmc26

3
@ jpmc26, 중복 또는 정규화와 관련된 문제는 전혀 없습니다. 서로 게이트 키는 자연 키의 값에 의미있는 연결이 없으므로 변경할 필요가 없습니다. 정규화와 관련하여 어떤 정규화 문제에 대해 이야기하고 있습니까? 정규화는 관계의 의미있는 속성에 적용됩니다. 대리 키의 숫자 값 (실제로 대리 키 자체의 개념)은 정규화 컨텍스트 외부에 있습니다.
Charles Bretana

1
이 표에 서로 다른 키, 예를 들어 frpom 1 ~ 50과 같은 값이 있지만 주 우편 번호에 다른 고유 색인이나 키를 넣지 않은 경우 (그리고 내 의견으로는, 주 이름에서도), 누군가 다른 대리 키 값을 갖지만 동일한 우편 번호 및 / 또는 주 이름을 가진 두 행을 입력하지 못하게하는 것은 무엇입니까? 'NJ', 'New Jersey'에 두 개의 행이 있으면 클라이언트 앱이 어떻게 처리합니까? 자연 키는 데이터 일관성을 보장합니다!
Charles Bretana

81

성능에 관한 것이 아닙니다. 좋은 기본 키를 만드는 것입니다. 시간이 지남에 따라 독특하고 변하지 않는. 국가 코드와 같은 엔터티는 시간이 지나도 변하지 않으며 기본 키의 좋은 후보가 될 수 있습니다. 그러나 쓴 경험은 드물다.

INT AUTO_INCREMENT는 "고유하고 변하지 않는 시간이 지남에 따라"조건을 충족합니다. 따라서 선호도.


25
진실. 저의 가장 큰 데이터베이스 중 하나에 유고 슬라비아와 소련에 대한 항목이 있습니다. 그들이 기본 키가 아니라서 다행입니다.
Paul Tomblin

8
@Steve, 왜 ANSI SQL이 ON UPDATE CASCADE에 대한 구문을 지원합니까?
Bill Karwin

5
불변성은 키의 요구 사항이 아닙니다. 어쨌든 대리 키도 때때로 변경됩니다. 필요한 경우 키를 변경해도 아무런 문제가 없습니다.
nvogel

9
폴, 데이터베이스에서 소련을 러시아로 바꿨나요? 그리고 SU가 존재하지 않는 척? 그리고 SU에 대한 모든 언급은 이제 러시아를 가리키는가?
Dainius

6
@ alga 나는 SU에서 태어 났으므로 그것이 무엇인지 안다.
Dainius

52

이 온라인에 대한 벤치 마크가 부족하여 약간 화가 났으므로 테스트를 직접 실행했습니다.

정기적 인 기본 작업은하지 않으므로 의도하지 않은 결과에 영향을 줄 수있는 요인에 대한 설정 및 단계를 확인하고 우려 사항을 의견에 게시하십시오.

설정은 다음과 같습니다.

  • 인텔 ® 코어 ™ i7-7500U CPU @ 2.70GHz × 4
  • 15.6 GiB RAM으로 테스트 중에 약 8GB의 여유 공간이 확보되었습니다.
  • 충분한 여유 공간이있는 148.6GB SSD 드라이브.
  • 우분투 16.04 64 비트
  • Linux 용 MySQL Ver 14.14 Distrib 5.7.20 (x86_64)

테이블 :

create table jan_int (data1 varchar(255), data2 int(10), myindex tinyint(4)) ENGINE=InnoDB;
create table jan_int_index (data1 varchar(255), data2 int(10), myindex tinyint(4), INDEX (myindex)) ENGINE=InnoDB;
create table jan_char (data1 varchar(255), data2 int(10), myindex char(6)) ENGINE=InnoDB;
create table jan_char_index (data1 varchar(255), data2 int(10), myindex char(6), INDEX (myindex)) ENGINE=InnoDB;
create table jan_varchar (data1 varchar(255), data2 int(10), myindex varchar(63)) ENGINE=InnoDB;
create table jan_varchar_index (data1 varchar(255), data2 int(10), myindex varchar(63), INDEX (myindex)) ENGINE=InnoDB;

그런 다음 각 테이블의 천만 행을 본질이 다음과 같은 PHP 스크립트로 채웠습니다.

$pdo = get_pdo();

$keys = [ 'alabam', 'massac', 'newyor', 'newham', 'delawa', 'califo', 'nevada', 'texas_', 'florid', 'ohio__' ];

for ($k = 0; $k < 10; $k++) {
    for ($j = 0; $j < 1000; $j++) {
        $val = '';
        for ($i = 0; $i < 1000; $i++) {
            $val .= '("' . generate_random_string() . '", ' . rand (0, 10000) . ', "' . ($keys[rand(0, 9)]) . '"),';
        }
        $val = rtrim($val, ',');
        $pdo->query('INSERT INTO jan_char VALUES ' . $val);
    }
    echo "\n" . ($k + 1) . ' millon(s) rows inserted.';
}

들어 int테이블, 비트는 ($keys[rand(0, 9)])단지로 대체 rand(0, 9)하고, 위해 varchar테이블, 나는 절단 또는 6 자로 확장하지 않고, 전체 미국 주 이름을 사용했다. generate_random_string()10 자의 임의 문자열을 생성합니다.

그런 다음 MySQL에서 실행했습니다.

  • SET SESSION query_cache_type=0;
  • 들어 jan_int테이블 :
    • SELECT count(*) FROM jan_int WHERE myindex = 5;
    • SELECT BENCHMARK(1000000000, (SELECT count(*) FROM jan_int WHERE myindex = 5));
  • 와 상기와 같은 다른 테이블에 대해서는 myindex = 'califo'위한 char테이블 myindex = 'california'에 대한 varchar테이블.

BENCHMARK각 테이블 에 대한 쿼리 시간 :

  • jan_int : 21.30 초
  • jan_int_index : 18.79 초
  • jan_char : 21.70 초
  • jan_char_index : 18.85 초
  • jan_varchar : 21.76 초
  • jan_varchar_index : 18.86 초

테이블 및 인덱스 크기와 관련하여 다음과 같은 결과가 표시됩니다 show table status from janperformancetest;(몇 개의 열은 표시되지 않음).

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Name              | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Collation              |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| jan_int           | InnoDB |      10 | Dynamic    | 9739094 |             43 |   422510592 |               0 |            0 |   4194304 |           NULL | utf8mb4_unicode_520_ci |  
| jan_int_index     | InnoDB |      10 | Dynamic    | 9740329 |             43 |   420413440 |               0 |    132857856 |   7340032 |           NULL | utf8mb4_unicode_520_ci |   
| jan_char          | InnoDB |      10 | Dynamic    | 9726613 |             51 |   500170752 |               0 |            0 |   5242880 |           NULL | utf8mb4_unicode_520_ci |  
| jan_char_index    | InnoDB |      10 | Dynamic    | 9719059 |             52 |   513802240 |               0 |    202342400 |   5242880 |           NULL | utf8mb4_unicode_520_ci |  
| jan_varchar       | InnoDB |      10 | Dynamic    | 9722049 |             53 |   521142272 |               0 |            0 |   7340032 |           NULL | utf8mb4_unicode_520_ci |   
| jan_varchar_index | InnoDB |      10 | Dynamic    | 9738381 |             49 |   486539264 |               0 |    202375168 |   7340032 |           NULL | utf8mb4_unicode_520_ci | 
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

필자의 결론은이 특정 사용 사례에서 성능 차이가 없다는 것입니다.


나는 그것이 늦었다는 것을 알고 있지만, where 조건에 대해 덜 이상적인 문자열을 선택했다면 결과를보고 싶어했을 것입니다. "califo [rnia]"는 첫 번째 문자를 비교 한 후 불일치를 버릴 수 있기 때문에 이상적이며 실제 일치 항목 만 더 확인하면됩니다. "newham"과 같은 것은 더 많은 캐릭터를 비교하여 모든 불일치를 제거하기 때문에 더 흥미로운 결과를 주었을 것입니다. 또한 정수를 제한하여 확률을 쌓을 수도 있습니다 .26 개 이상의 값을 지정했을 것 입니다.
Uueerdo

15
10 살짜리 질문에서 이것은 추측이 아니라 실제 벤치 마크에 의존하는 두 가지 답변 중 하나 일뿐입니다.
Adrian Baker

1
그러나 테이블에는 기본 키가 없으며 실제로 InnoDB에서는 정렬 된 데이터 구조입니다. 정수 정렬과 문자열 정렬 사이의 속도는 달라야합니다.
Melkor

1
내가 INDEX대신 사용 하는 @Melkor Fair point PRIMARY KEY. 나는 나의 추론을 기억하지 않는다 - 아마 가정 PRIMARY KEY단지입니다 INDEX고유성 제약 조건. 그러나 federico-razzoli.com/primary-key-in-innodb의 InnoDB에 물건이 저장되는 방법에 대한 섹션을 읽으면 결과가 여전히 기본 키에 적용되며 가치 조회 성능 차이에 대한 질문에 대답한다고 생각합니다. 또한 귀하의 의견은 정렬 알고리즘의 성능을 살펴볼 것을 제안 합니다.이 알고리즘은 조사한 유스 케이스에는 적용되지 않으며 세트의 값을 찾습니다 .
Jan Żankowski

1
조회 작업에서는 기본 키 필드 (바이너리 검색과 같은)를 비교해야합니다. 여기서 int는 varchar보다 약간 빠릅니다. 그러나 실험에서 제안한 것처럼 그다지 명확하지 않습니다 (또는 기본 키가 없어서 쿼리 속도가 느려졌 기 때문일 수 있음). 나는 그것이 삽입과 조회에서 같은 것이라고 생각합니다.
Melkor

38

길이에 따라 다릅니다. varchar가 20 자이고 int가 4 인 경우 int를 사용하면 인덱스는 디스크의 인덱스 공간 페이지 당 노드 수의 5 배가됩니다. 인덱스는 물리적 및 / 또는 논리적 읽기의 5 분의 1이 필요합니다.

따라서 기회가 주어지면 성능이 문제가되는 경우 항상 테이블 및 이러한 테이블의 행을 참조하는 외래 키에 의미가없는 필수 키 (대리라고 함)를 사용하십시오.

동시에 , 보증 데이터의 일관성, 그것은 중요한 모든 테이블은해야한다 또한 중복 행이 (의미있는 테이블 속성에 기반하여 중복)에 삽입 될 수 없음을 보장하기 위해 의미있는 숫자가 아닌 대체 키 (또는 고유 색인)를 가지고있다.

특정 용도의 경우 (상태 조회와 같은) 테이블 크기가 너무 작기 때문에 실제로 중요하지 않습니다. 일반적으로 행 수가 수천 개 미만인 테이블의 인덱스 성능에 영향을 미치지 않습니다. ..


확실한? 행을 기준으로 가장 많은 데이터 형식을 제공합니까? 키 외에 다른 데이터가 있습니다. 요소 5가 아닌가?
ManuelSchneid3r

1
@ manuelSchneid3r, 무엇? 우 토피? 아니요, 요소 5는 "utopic"이 아닙니다. 4로 나눈 값은 20입니다. "데이터 형식 행 기반"이란 무엇입니까? 인덱스는 "행 기반"이 아니며 균형 잡힌 트리 구조입니다.
Charles Bretana

36

절대적으로하지.

INT, VARCHAR 및 CHAR 사이에서 몇 가지 ... 몇 가지 ... 성능 검사를 수행했습니다.

PRIMARY KEY (독특하고 클러스터 된)가있는 천만 개의 레코드 테이블은 내가 사용한 세 가지 중 어느 것에 관계없이 동일한 속도와 성능 (및 하위 트리 비용)을 가졌습니다.

그 말은 ... 응용 프로그램에 가장 적합한 것을 사용하십시오. 성능에 대해 걱정하지 마십시오.


42
varchars의 길이를 모른 채 무의미합니다 ... 100 바이트 너비 인 경우 4 바이트 int와 동일한 성능을 얻지 못합니다
Charles Bretana

6
또한 사용중인 데이터베이스와 데이터베이스 버전을 확인하는 데 도움이됩니다. 성능 조정은 거의 항상 버전마다 작동하고 향상되었습니다.
Dave Black

VARCHAR는 확실히 인덱스 크기에 대한 문제. 그리고 인덱스는 메모리에 얼마나 많은 양을 넣을 수 있는지 결정합니다. 그리고 메모리의 인덱스는 그렇지 않은 인덱스보다 훨씬 빠릅니다. 10m 행의 경우 해당 인덱스에 250MB의 메모리를 사용할 수 있었으며 괜찮 았습니다. 그러나 100m 행이 있으면 해당 메모리의 품질이 떨어집니다.
Paul Draper

9

짧은 코드의 경우 차이가 없을 것입니다. 이러한 코드를 보유하고있는 테이블이 매우 작고 (최대 2 천 행) 자주 변경되지 않는 경우 (마지막으로 새 미국 주를 추가 한 경우)에 특히 그렇습니다.

키 사이에 차이가 더 큰 테이블의 경우 위험 할 수 있습니다. 예를 들어, 사용자 테이블에서 전자 우편 주소 / 사용자 이름을 사용하는 것을 고려하십시오. 사용자 수가 수백만 명이고 일부 사용자의 이름이나 전자 메일 주소가 길면 어떻게됩니까? 이제 해당 키를 사용하여이 테이블을 조인해야 할 때마다 훨씬 비쌉니다.


2
이것이 비싸다는 것을 알고 있습니까? 아니면 그냥 추측하고 있습니까?
Steve McLeod

물론 그것은 rdbms 구현에 달려 있지만, 대부분의 서버는 인덱싱 목적으로 실제 값의 해시를 유지한다는 것을 이해합니다. 그럼에도 불구하고 상대적으로 짧은 해시 (예 : 10 바이트) 인 경우에도 2 4 바이트 int보다 2 10 바이트 해시를 비교하는 것이 여전히 더 효과적입니다.
Joel Coehoorn

조인에 긴 (넓은) 키를 사용하지 마십시오. 그러나 테이블의 행에 고유 한 항목을 가장 잘 나타내는 경우에는 고유 키 (또는 동일한 인덱스)가 있어야합니다. 그 자연적인 가치를 사용하는 표. 열쇠는 조인을 위해 존재하지 않으며, 당신의 마음이 원하는 무엇이든 참여할 수 있습니다. 데이터 일관성을 보장하기위한 키가 있습니다.
Charles Bretana

6

기본 키의 경우 물리적으로 행을 고유하게 만드는 것은 기본 키로 결정해야합니다.

외래 키로 참조하려면 자동 증분 정수를 서로 게이트로 사용하는 것이 두 가지 주요 이유에서 좋은 아이디어입니다.
-첫째, 일반적으로 조인에서 발생하는 오버 헤드가 줄어 듭니다.
-둘째, 고유 varchar가 포함 된 테이블을 업데이트 해야하는 경우 업데이트는 모든 자식 테이블로 계단식으로 내려와 인덱스뿐만 아니라 모든 자식 테이블로 업데이트해야하지만 int surrogate는 업데이트해야합니다. 마스터 테이블과 인덱스입니다.

대리 사용의 단점은 대리의 의미를 변경할 수 있다는 것입니다.

ex.
id value
1 A
2 B
3 C

Update 3 to D
id value
1 A
2 B
3 D

Update 2 to C
id value
1 A
2 C
3 D

Update 3 to B
id value
1 A
2 C
3 B

그것은 모두 당신이 정말로 당신의 구조에서 걱정해야 할 것과 가장 의미하는 것에 달려 있습니다.


3

대리자 AUTO_INCREMENT가 아프게 되는 일반적인 경우 :

일반적인 스키마 패턴은 다 대다 매핑입니다 .

CREATE TABLE map (
    id ... AUTO_INCREMENT,
    foo_id ...,
    bar_id ...,
    PRIMARY KEY(id),
    UNIQUE(foo_id, bar_id),
    INDEX(bar_id) );

이 패턴의 성능은 특히 InnoDB를 사용할 때 훨씬 좋습니다.

CREATE TABLE map (
    # No surrogate
    foo_id ...,
    bar_id ...,
    PRIMARY KEY(foo_id, bar_id),
    INDEX      (bar_id, foo_id) );

왜?

  • InnoDB 2 차 키에는 추가 조회가 필요합니다. PK로 쌍을 이동하면 한 방향으로 피할 수 있습니다.
  • 보조 인덱스는 "커버링"이므로 추가 조회가 필요하지 않습니다.
  • 이 테이블은 제거 id되고 하나의 인덱스로 인해 더 작습니다 .

다른 경우 ( 국가 ) :

country_id INT ...
-- versus
country_code CHAR(2) CHARACTER SET ascii

너무 자주 초보자 INT는 거의 변하지 않는 2 바이트 문자열 인 '자연'2 바이트를 사용하는 대신 country_code를 4 바이트로 정규화 합니다. 더 빠르고, 더 작고, 더 적은 JOIN, 더 읽기 쉽습니다.


2

HauteLook에서는 자연 키를 사용하도록 많은 테이블을 변경했습니다. 실제 성능 향상을 경험했습니다. 언급했듯이 많은 쿼리가 이제 더 적은 조인을 사용하여 쿼리 성능을 향상시킵니다. 이해가된다면 복합 기본 키를 사용할 것입니다. 즉, 일부 테이블에는 서로 게이트 키가 있으면 작업하기가 더 쉽습니다.

또한 사람들이 데이터베이스에 인터페이스를 쓰도록 허용하는 경우 대리 키가 도움이 될 수 있습니다. 타사는 대리 키가 매우 드문 상황에서만 변경 될 수 있다는 사실에 의존 할 수 있습니다.


2

나는 같은 딜레마에 직면했다. 나는 3 가지 팩트 테이블, 도로 사고, 사고 차량 및 사고 사고로 DW (별자리 스키마)를 만들었습니다. 데이터에는 1979 년부터 2012 년까지 영국에서 기록 된 모든 사고와 60 개의 차원 테이블이 포함됩니다. 약 2 천만 건의 기록.

팩트 테이블 관계 :

+----------+          +---------+
| Accident |>--------<| Vehicle |
+-----v----+ 1      * +----v----+
     1|                    |1
      |    +----------+    |
      +---<| Casualty |>---+
         * +----------+ *

RDMS : MySQL 5.6

기본적으로 사고 색인은 15 자리 숫자의 varchar (숫자 및 문자)입니다. 사고 색인이 변경되지 않으면 대리 키를 사용하지 않으려 고했습니다. i7 (8 코어) 컴퓨터에서 DW는 치수에 따라 1,200 만 건의로드 레코드 이후 쿼리하기에 너무 느려졌습니다. 많은 재 작업을하고 bigint surrogate 키를 추가 한 후 평균 20 % 속도 성능 향상을 얻었습니다. 그러나 성능 향상은 낮지 만 유효한 시도입니다. MySQL 튜닝 및 클러스터링에서 일하고 있습니다.


1
파티셔닝을 살펴 봐야 할 것 같습니다.
jcoffland

2

문제는 MySQL에 관한 것이므로 큰 차이가 있다고 말합니다. 오라클에 관한 것이라면 (숫자를 문자열로 저장합니다-예, 처음에는 믿을 수 없었습니다) 큰 차이가 없습니다.

테이블의 스토리지는 문제가 아니지만 업데이트 및 색인 참조입니다. 기본 키를 기반으로 레코드를 조회하는 쿼리는 자주 발생합니다. 자주 발생하기 때문에 가능한 빨리 발생하기를 원합니다.

문제는 CPU가 4 바이트 및 8 바이트 정수를 실리콘 으로 자연스럽게 처리한다는 것입니다 . 두 정수를 비교하는 것이 정말 빠릅니다. 하나 또는 두 개의 클럭 사이클에서 발생합니다.

이제 문자열을보십시오-많은 문자로 구성되어 있습니다 (요즘 문자 당 1 바이트 이상). 우선 순위를 위해 두 문자열을 비교하는 것은 한두 번의 주기로 수행 될 수 없습니다. 대신 차이가 발견 될 때까지 문자열 문자를 반복해야합니다. 일부 데이터베이스에서는 더 빠르게 할 수있는 트릭이 있다고 확신하지만 CPU에 의해 실리콘에서 int 비교가 자연스럽고 번개처럼 빠르기 때문에 여기서는 관련이 없습니다.

내 일반적인 규칙-모든 기본 키는 객체간에 많은 관계가있는 ORM (Hibernate, Datanucleus 등)을 사용하는 OO 앱에서 자동 증가 INT이어야합니다. 일반적으로 항상 간단한 FK로 구현됩니다. 이러한 빠른 문제 해결을위한 DB는 앱의 응답성에 중요합니다.


0

성능에 대한 영향은 확실하지 않지만 최소한 개발 중에는 자동 증분 된 정수 "대리"키와 원하는 고유 한 "자연"키를 모두 포함하는 것이 타협 할 수 있습니다. 이를 통해 성능 및 자연 키의 변경 가능성을 포함한 다른 가능한 문제를 평가할 수 있습니다.


0

평소와 같이 담요 답변이 없습니다. '때에 따라 다르지!' 그리고 나는 안면이 아닙니다. 원래 질문에 대한 나의 이해는 국가 (정수 ID 또는 문자 / varchar 코드)와 같은 작은 테이블의 키가 주소 / 연락처 테이블과 같은 잠재적으로 거대한 테이블의 외래 키라는 것이 었습니다.

DB에서 데이터를 다시 원할 때 두 가지 시나리오가 있습니다. 첫 번째는 모든 연락처를 주 및 국가 코드 또는 이름으로 나열하려는 목록 / 검색 종류의 쿼리입니다 (ID는 도움이되지 않으므로 조회가 필요함). 다른 하나는 주, 국가 이름을 표시해야하는 단일 연락처 레코드를 표시하는 기본 키의 Get 시나리오입니다.

후자의 경우에는 단일 레코드 또는 몇 개의 레코드와 키 읽기에 대한 테이블을 모으기 때문에 FK가 무엇을 기반으로하는지는 중요하지 않습니다. 전자 (검색 또는 목록) 시나리오는 우리의 선택에 영향을받을 수 있습니다. 국가 (적어도 인식 가능한 코드 및 아마도 검색 자체에 국가 코드가 포함되어 있음)를 표시해야하기 때문에 대리 키를 통해 다른 테이블을 조인하지 않아도 잠재적으로 (실제 테스트를 수행하지 않았기 때문에 여기서는 신중합니다) 이것은 성능이 향상 될 가능성이 높은 것으로 보입니다. 검색에 도움이된다는 사실에도 불구하고.

코드는 크기가 작기 때문에 일반적으로 국가와 주에 대해 3 자 이하 여야합니다.이 시나리오에서는 자연 키를 외래 키로 사용하는 것이 좋습니다.

키가 더 긴 varchar 값 및 더 큰 테이블에 의존하는 다른 시나리오. 대리 키는 아마도 이점이 있습니다.


0

성능 범위를 고려하여 차이가 있음을 분명히 말할 수 있습니다.

1- 코드 나 쿼리에서 ToUpper (), ToLower (), ToUpperInvarient () 또는 ToLowerInvarient ()를 사용할 필요가없고이 4 가지 함수의 성능 벤치 마크가 다르기 때문에 대리 int를 사용하는 것이 응용 프로그램에서 더 빠릅니다. 이에 대한 Microsoft 성능 규칙을 참조하십시오. (신청 실적)

2- surrogate int를 사용하면 시간이 지나도 키가 변경되지 않습니다. 국가 코드도 변경 될 수 있습니다. Wikipedia에서 ISO 코드가 시간이 지남에 따라 어떻게 바뀌 었는지 확인하십시오. 서브 트리의 기본 키를 변경하려면 많은 시간이 걸립니다. (데이터 유지 관리 성능)

3- PK / FK가 int가 아닌 경우 NHibernate와 같은 ORM 솔루션에 문제가있는 것 같습니다. (개발자 성능)

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