C'è una differenza di prestazioni REALE tra le chiavi primarie INT e VARCHAR?


174

Esiste una differenza misurabile delle prestazioni tra l'utilizzo di INT e VARCHAR come chiave primaria in MySQL? Vorrei utilizzare VARCHAR come chiave primaria per gli elenchi di riferimento (pensa agli Stati Uniti, ai codici Paese) e un collega non si muoverà su INT AUTO_INCREMENT come chiave primaria per tutte le tabelle.

Il mio argomento, come dettagliato qui , è che la differenza di prestazioni tra INT e VARCHAR è trascurabile, poiché ogni riferimento a chiave esterna INT richiederà un JOIN per dare un senso al riferimento, una chiave VARCHAR presenterà direttamente le informazioni.

Quindi, qualcuno ha esperienza con questo particolare caso d'uso e le preoccupazioni relative alle prestazioni ad esso associate?


3
Ho scritto un post con la risposta "no" con alcuni dettagli dei test che ho eseguito ... ma quello era SQL Server, non MySQL. Quindi ho cancellato la mia risposta.
Timothy Khouri,

17
@Timothy - non avresti dovuto cancellarlo. Stavo per votare. La maggior parte dei server di database SQL ha pianificatori di query simili e strozzature di prestazioni simili.
Paul Tomblin,

9
@ Timothy ripubblicare i risultati.
Jake McGraw,

2
Tanti commenti e risposte presuppongono che le chiavi siano lì per essere utilizzate per i join. Non sono. Le chiavi sono lì per essere utilizzate per coerenza dei dati - per evitare righe duplicate (più di una riga che rappresenta la stessa entità). Qualsiasi colonna (o insieme di colonne) può essere utilizzata in un join e per garantire che il join sia uno-a-zero o che molte colonne debbano semplicemente essere univoche. Qualsiasi indice univoco lo garantisce e non deve essere significativo.
Charles Bretana,

Risposte:


78

Fai notare che puoi evitare un certo numero di query unite utilizzando quella che viene chiamata una chiave naturale anziché una chiave surrogata . Solo tu puoi valutare se il vantaggio di questo è significativo nella tua applicazione.

Cioè, puoi misurare le query nella tua applicazione che sono le più importanti per essere veloci, perché funzionano con grandi volumi di dati o vengono eseguite molto frequentemente. Se queste query traggono vantaggio dall'eliminazione di un join e non risentono dell'utilizzo di una chiave primaria varchar, quindi farlo.

Non utilizzare nessuna strategia per tutte le tabelle nel database. È probabile che in alcuni casi una chiave naturale sia migliore, ma in altri casi una chiave surrogata è migliore.

Altre persone sottolineano che in pratica è raro che una chiave naturale non cambi mai o abbia duplicati, quindi le chiavi surrogate di solito valgono la pena.


3
E a volte (imho, spesso), entrambi sono migliori, il surrogato da utilizzare per i riferimenti FK in altre tabelle e per Joins, e la chiave naturale per garantire la coerenza dei dati
Charles Bretana,

@CharlesBretana È interessante. L'uso di una chiave naturale per la coerenza dei dati lungo l'FK è una pratica comune? Il mio primo pensiero è stato che l'archiviazione aggiuntiva che sarebbe richiesta su tavoli di grandi dimensioni potrebbe non valerne la pena. Qualsiasi informazione è apprezzata Cordiali saluti - Ho un discreto background di programmazione ma la mia esperienza SQL è limitata principalmente alle query SELECT
Rob

2
@CharlesBretana Quando leggo "memorizzali entrambi", penso che "ridondanza" e "non normalizzato", che equivale a "Questa roba potrebbe essere rovinata" e "Devo assicurarmi che entrambi vengano cambiati se ne viene mai cambiato uno". Se si dispone di ridondanza, dovrebbe esserci un motivo molto valido (come prestazioni del tutto inaccettabili) perché la ridondanza è sempre potenziale affinché i dati diventino incoerenti.
jpmc26,

3
@ jpmc26, NON sono assolutamente coinvolti problemi di ridondanza o normalizzazione. Una chiave surrogata non ha una connessione significativa ai valori in una chiave naturale, quindi non dovrebbe mai essere cambiata. Per quanto riguarda la normalizzazione, di quali problemi di normalizzazione stai parlando? La normalizzazione si applica agli attributi significativi di una relazione; il valore numerico di una chiave surrogata, (anzi, il concetto stesso di chiave surrogata stessa) si trova completamente al di fuori del contesto di qualsiasi normalizzazione.
Charles Bretana,

1
E per rispondere alla tua altra domanda, in particolare su una tabella di stati, se in questa tabella avevi una chiave surrogata, con valori, diciamo da 1 a 50, ma NON hai inserito un altro indice o chiave univoco nel codice postale dello stato, (e, a mio avviso, anche sul nome dello stato), allora cosa impedisce a qualcuno di inserire due righe con valori chiave surrogati diversi ma con lo stesso codice postale e / o nome stato? Come la gestirà l'app client se ci fossero due file con "NJ", "New Jersey"? Le chiavi naturali assicurano la coerenza dei dati!
Charles Bretana,

81

Non si tratta di prestazioni. Riguarda ciò che rende una buona chiave primaria. Unico e immutabile nel tempo. Potresti pensare che un'entità come un prefisso internazionale non cambi mai nel tempo e sarebbe un buon candidato per una chiave primaria. Ma l'amara esperienza è che raramente è così.

INT AUTO_INCREMENT soddisfa la condizione "unica e immutabile nel tempo". Da qui la preferenza.


25
Vero. Uno dei miei più grandi database contiene voci per la Jugoslavia e l'Unione Sovietica. Sono contento che non siano chiavi primarie.
Paul Tomblin,

8
@Steve, allora perché ANSI SQL supporta la sintassi per ON UPDATE CASCADE?
Bill Karwin,

5
L'immutabilità non è un requisito di una chiave. In ogni caso, a volte cambiano anche le chiavi surrogate. Nulla di sbagliato nel cambiare le chiavi, se necessario.
nvogel,

9
Paul, quindi hai cambiato l'Unione Sovietica in Russia nel tuo database? E far finta che SU non esista mai? E tutti i riferimenti a SU ora indicano la Russia?
Dainius,

6
@alga Sono nato a SU, quindi so di cosa si tratta.
Dainius,

52

Ero un po 'infastidito dalla mancanza di benchmark per questo online, quindi ho eseguito un test da solo.

Nota però che non lo faccio regolarmente, quindi controlla la mia configurazione e i passaggi per eventuali fattori che potrebbero aver influenzato i risultati involontariamente e pubblica i tuoi dubbi nei commenti.

L'impostazione era la seguente:

  • CPU Intel® Core ™ i7-7500U a 2,70 GHz × 4
  • 15,6 GB di RAM, di cui ho assicurato che circa 8 GB erano liberi durante il test.
  • Unità SSD da 148,6 GB, con molto spazio libero.
  • Ubuntu 16.04 a 64 bit
  • MySQL Ver 14.14 Distrib 5.7.20, per Linux (x86_64)

Le tavole:

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;

Quindi, ho riempito 10 milioni di righe in ogni tabella con uno script PHP la cui essenza è così:

$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.';
}

Per le inttabelle, il bit è ($keys[rand(0, 9)])stato sostituito con just rand(0, 9)e per le varchartabelle ho usato i nomi completi degli stati USA, senza tagliarli o estenderli a 6 caratteri.generate_random_string()genera una stringa casuale di 10 caratteri.

Poi ho funzionato in MySQL:

  • SET SESSION query_cache_type=0;
  • Per jan_inttavolo:
    • SELECT count(*) FROM jan_int WHERE myindex = 5;
    • SELECT BENCHMARK(1000000000, (SELECT count(*) FROM jan_int WHERE myindex = 5));
  • Per altre tabelle, come sopra, con myindex = 'califo'per chartavoli e myindex = 'california'per varchartavoli.

Tempi della BENCHMARKquery su ciascuna tabella:

  • gen_int: 21.30 sec
  • jan_int_index: 18.79 sec
  • jan_char: 21.70 sec
  • jan_char_index: 18,85 sec
  • jan_varchar: 21.76 sec
  • jan_varchar_index: 18,86 sec

Per quanto riguarda le dimensioni di tabella e indice, ecco l'output di show table status from janperformancetest;(con alcune colonne non mostrate):

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 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 | 
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

La mia conclusione è che non ci sono differenze di prestazioni per questo particolare caso d'uso.


So che è tardi ora, ma sarei stato curioso di vedere i risultati se avessi scelto una stringa meno ideale per la condizione in cui. "califo [rnia]" era l'ideale in quanto poteva scartare i disallineamenti dopo aver confrontato il primo personaggio, avendo solo bisogno di controllare ulteriormente le partite reali; qualcosa come "newham" avrebbe dato risultati più interessanti in quanto sarebbe nuovo confrontare più personaggi per eliminare tutte le discrepanze. Inoltre, limitando i tuoi numeri interi in questo modo si accumulano anche le probabilità contro di loro, avrei dato loro almeno 26 valori.
Uueerdo,

15
Incredibile che in una domanda di 10 anni, questa è solo una delle due risposte che non è solo una speculazione e si basa su benchmark reali.
Adrian Baker,

1
Ma le tue tabelle non hanno una chiave primaria, che in realtà in InnoDB è una struttura di dati ordinata. La velocità tra l'ordinamento intero e l'ordinamento delle stringhe dovrebbe essere diversa.
Melkor,

1
@Melkor Fair point che uso al INDEXposto di PRIMARY KEY. Non ricordo il mio ragionamento - probabilmente ho pensato che PRIMARY KEYfosse solo un INDEXvincolo di unicità. Tuttavia, leggendo la sezione su come vengono archiviate le cose in InnoDB in federico-razzoli.com/primary-key-in-innodb , penso che i miei risultati si applichino ancora alle chiavi primarie e risponda alla domanda sulla differenza di prestazioni della ricerca del valore. Inoltre, il tuo commento suggerisce di osservare le prestazioni degli algoritmi di ordinamento , che non si applicano al caso d'uso che indaga, che sta cercando valori in un set.
Jan Żankowski,

1
L'operazione di ricerca richiede anche confronti sul campo chiave primaria (come una ricerca binaria), dove int dovrebbe essere un po 'più veloce di varchar. Ma come suggerito dai tuoi esperimenti, non è così ovvio (o forse perché non avevi una chiave primaria, quindi le query erano tutte più lente). Penso che sia la stessa cosa per l'inserimento e la ricerca.
Melkor,

38

Dipende dalla lunghezza .. Se varchar avrà 20 caratteri e int è 4, quindi se si utilizza un int, l'indice avrà CINQUE volte il numero di nodi per pagina dello spazio indice sul disco ... Ciò significa che l'attraversamento l'indice richiederà un quinto di quante letture fisiche e / o logiche.

Quindi, se le prestazioni sono un problema, data l'opportunità, usa sempre una chiave integrale non significativa (chiamata surrogata) per le tue tabelle e per le chiavi esterne che fanno riferimento alle righe in queste tabelle ...

Allo stesso tempo , per la coerenza dei dati di garanzia, ogni tavolo dove conta dovrebbe anche avere una chiave alternativa non numerica significativa (o un indice univoco) per garantire che le righe duplicate non possano essere inserite (duplicate in base ad attributi di tabella significativi).

Per l'uso specifico di cui stai parlando (come le ricerche di stato) non importa davvero perché la dimensione della tabella è così piccola .. In generale non vi è alcun impatto sulle prestazioni degli indici su tabelle con meno di qualche migliaio di righe. ..


Sicuro? Non hai la maggior parte dei formati di dati basati su riga? Ci sono altri dati oltre alle chiavi. Il fattore 5 non è utopico?
ManuelSchneid3r,

1
@ manuelSchneid3r, What? utopico? No, il fattore 5 non è "utopico". È solo 20 diviso per 4. E cosa significa "formato file basato su righe"? Gli indici non sono "basati su righe", sono strutture ad albero bilanciate.
Charles Bretana,

36

Assolutamente no.

Ho fatto diversi ... diversi ... controlli delle prestazioni tra INT, VARCHAR e CHAR.

La tabella da 10 milioni di record con un CHIAVE PRIMARIA (unica e raggruppata) aveva la stessa identica velocità e prestazioni (e costi di sottostruttura) indipendentemente da quale delle tre ho usato.

Detto questo ... usa tutto ciò che è meglio per la tua applicazione. Non preoccuparti per le prestazioni.


42
insignificante senza sapere quanto tempo fossero i varchar ... Se fossero 100 byte widem, allora ti garantivo che non otterrai le stesse prestazioni di un int a 4 byte
Charles Bretana,

6
Aiuterebbe anche a sapere quale database si sta utilizzando e quale versione del database. Il tuning delle prestazioni è quasi sempre lavorato e migliorato da una versione all'altra.
Dave Black,

VARCHAR è sicuramente importante per la dimensione dell'indice. E l'indice determina quanto può essere adattato alla memoria. E gli indici in memoria sono molto, molto più veloci di quelli che non lo sono. Potrebbe essere che per le tue file da 10m, tu avessi 250 MB di memoria disponibile per quell'indice, e andava bene. Ma se hai 100m di file, starai meno bene in quel ricordo.
Paul Draper,

9

Per i codici funzione, probabilmente non c'è differenza. Ciò è particolarmente vero in quanto è probabile che la tabella contenente questi codici sia molto piccola (al massimo un paio di migliaia di righe) e non cambi spesso (quando è l'ultima volta che abbiamo aggiunto un nuovo Stato USA).

Per tavoli più grandi con una variazione più ampia tra i tasti, questo può essere pericoloso. Pensa ad esempio a utilizzare l'indirizzo e-mail / il nome utente da una tabella utente. Cosa succede quando hai pochi milioni di utenti e alcuni di questi utenti hanno nomi lunghi o indirizzi e-mail. Ora, ogni volta che devi unirti a questa tabella usando quella chiave diventa molto più costosa.


2
Sai per certo che sarebbe costoso? O stai solo indovinando?
Steve McLeod,

Naturalmente dipende dall'implementazione di rdbms, ma da quello che capisco la maggior parte dei server manterrà l'hash del valore effettivo a scopi di indicizzazione. Anche così, e anche se si tratta di un hash relativamente breve (diciamo, 10 byte), è ancora più difficile confrontare 2 hash da 10 byte con 2 inte da 4 byte.
Joel Coehoorn,

Non usare MAI una chiave lunga (ampia) per i join ... Ma se è la migliore rappresentazione di ciò che è unico per le righe nella tabella, allora è meglio che ci sia una chiave univoca (o indice - che è la stessa cosa) sul tabella usando quei valori naturali. Le chiavi non sono lì per i join, puoi unirti a tutto ciò che il tuo cuore desidera. Le chiavi sono lì per garantire la coerenza dei dati.
Charles Bretana,

6

Per quanto riguarda la chiave primaria, qualunque cosa renda fisicamente unica una riga dovrebbe essere determinata come chiave primaria.

Per un riferimento come chiave esterna, utilizzare un numero intero con incremento automatico come surrogato è una buona idea per due motivi principali.
- In primo luogo, di solito si verificano meno spese generali nell'unione.
- In secondo luogo, se è necessario aggiornare la tabella che contiene il varchar univoco, l'aggiornamento deve passare a cascata a tutte le tabelle figlio e aggiornarle tutte insieme agli indici, mentre con int surrogate, deve solo aggiornare il tabella principale e relativi indici.

Lo svantaggio dell'uso del surrogato è che potresti eventualmente permettere di cambiare il significato del surrogato:

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

Tutto dipende da ciò di cui devi davvero preoccuparti nella tua struttura e da ciò che significa di più.


3

Casi comuni in cui un surrogato AUTO_INCREMENT fa male:

Un modello di schema comune è un mapping molti-a-molti :

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

Le prestazioni di questo modello sono molto migliori, specialmente quando si utilizza InnoDB:

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

Perché?

  • Le chiavi secondarie di InnoDB richiedono una ricerca aggiuntiva; spostando la coppia nel PK, ciò viene evitato per una direzione.
  • L'indice secondario è "coprente", quindi non necessita della ricerca aggiuntiva.
  • Questa tabella è più piccola a causa dell'eliminazione di idun indice.

Un altro caso ( paese ):

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

Troppo spesso il novizio normalizza country_code in un 4 byte INTinvece di usare una stringa "naturale" a 2 byte, quasi immutabile a 2 byte. Più JOIN più veloci, più piccoli, meno, più leggibili.


2

In HauteLook, abbiamo modificato molte delle nostre tabelle per utilizzare le chiavi naturali. Abbiamo sperimentato un aumento delle prestazioni nel mondo reale. Come accennato, molte delle nostre query ora utilizzano meno join, il che rende le query più performanti. Useremo anche una chiave primaria composita se ha senso. Detto questo, alcuni tavoli sono più facili da utilizzare se hanno una chiave surrogata.

Inoltre, se si consente alle persone di scrivere interfacce nel proprio database, una chiave surrogata può essere utile. La terza parte può fare affidamento sul fatto che la chiave surrogata cambierà solo in circostanze molto rare.


2

Ho affrontato lo stesso dilemma. Ho realizzato un DW (schema delle costellazioni) con 3 tabelle dei fatti, incidenti stradali, veicoli in incidenti e vittime in incidenti. I dati includono tutti gli incidenti registrati nel Regno Unito dal 1979 al 2012 e 60 tabelle dimensionali. Tutti insieme, circa 20 milioni di dischi.

Relazioni delle tabelle dei fatti:

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

RDMS: MySQL 5.6

Nativamente l'indice degli incidenti è un varchar (numeri e lettere), con 15 cifre. Ho cercato di non avere chiavi surrogate, una volta che gli indici degli incidenti non sarebbero mai cambiati. In un computer i7 (8 core), il DW è diventato troppo lento per eseguire una query dopo 12 milioni di record di carico a seconda delle dimensioni. Dopo un sacco di rielaborazioni e l'aggiunta di chiavi surrogate bigint ho ottenuto un aumento delle prestazioni della velocità media del 20%. Eppure a basso guadagno prestazionale, ma prova valida. Sto lavorando in MySQL tuning e clustering.


1
Sembra che tu debba guardare al partizionamento.
jcoffland,

2

La domanda riguarda MySQL, quindi dico che c'è una differenza significativa. Se si trattava di Oracle (che memorizza i numeri come stringa - sì, all'inizio non ci potevo credere), quindi non molta differenza.

L'archiviazione nella tabella non è il problema, ma lo è l'aggiornamento e il riferimento all'indice. Le domande che riguardano la ricerca di un record basato sulla sua chiave primaria sono frequenti: vuoi che si verifichino il più rapidamente possibile perché accadono così spesso.

Il fatto è che una CPU si occupa naturalmente di numeri interi a 4 e 8 byte, in silicio . È DAVVERO veloce per confrontare due numeri interi - succede in uno o due cicli di clock.

Ora guarda una stringa: è composta da molti caratteri (più di un byte per carattere in questi giorni). Il confronto tra due stringhe per precedenza non può essere eseguito in uno o due cicli. Invece i caratteri delle stringhe devono essere ripetuti fino a quando non viene rilevata una differenza. Sono sicuro che ci sono trucchi per renderlo più veloce in alcuni database, ma questo è irrilevante qui perché un confronto int viene fatto naturalmente e velocissimo nel silicio dalla CPU.

La mia regola generale - ogni chiave primaria dovrebbe essere un INT autoincrementante soprattutto nelle app OO che utilizzano un ORM (Hibernate, Datanucleus, qualunque cosa) in cui ci sono molte relazioni tra oggetti - di solito saranno sempre implementate come un semplice FK e l'abilità per DB per risolverli velocemente è importante per la reattività della tua app.


0

Non sono sicuro delle implicazioni sulle prestazioni, ma sembra un possibile compromesso, almeno durante lo sviluppo, sarebbe includere sia la chiave "surrogata" intera incrementata automaticamente, sia la chiave "naturale" intesa, unica. Ciò ti darebbe l'opportunità di valutare le prestazioni, così come altri possibili problemi, inclusa la possibilità di cambiare le chiavi naturali.


0

Come al solito, non ci sono risposte coperte. 'Dipende!' e non sono faceto. La mia comprensione della domanda originale era che le chiavi su piccole tabelle - come Paese (ID intero o codice char / varchar) essendo una chiave esterna per una tabella potenzialmente enorme come la tabella indirizzo / contatto.

Esistono due scenari qui quando si desidera ripristinare i dati dal DB. Il primo è un tipo di query elenco / ricerca in cui si desidera elencare tutti i contatti con codici o nomi di stato e paese (gli ID non aiuteranno e quindi avranno bisogno di una ricerca). L'altro è uno scenario get su chiave primaria che mostra un singolo record di contatto in cui deve essere mostrato il nome dello stato, il paese.

Per quest'ultimo, probabilmente non importa su cosa si basa l'FK poiché stiamo riunendo tabelle per un singolo record o pochi record e su letture chiave. Il primo scenario (ricerca o elenco) potrebbe essere influenzato dalla nostra scelta. Dal momento che è necessario mostrare il Paese (almeno un codice riconoscibile e forse anche la ricerca stessa include un codice Paese), non dover unire un altro tavolo tramite una chiave surrogata può potenzialmente (sono solo prudente qui perché non ho effettivamente testato questo, ma sembra altamente probabile) migliorare le prestazioni; nonostante il fatto che certamente aiuta con la ricerca.

Poiché i codici sono di piccole dimensioni, in genere non più di 3 caratteri per paese e stato, in questo scenario potrebbe essere opportuno utilizzare le chiavi naturali come chiavi esterne.

L'altro scenario in cui le chiavi dipendono da valori varchar più lunghi e forse da tabelle più grandi; la chiave surrogata ha probabilmente il vantaggio.


0

Consentitemi di dire di sì, c'è sicuramente una differenza, prendendo in considerazione l'ambito delle prestazioni (definizione predefinita):

1- L'uso di surrogate int è più veloce nell'applicazione perché non è necessario utilizzare ToUpper (), ToLower (), ToUpperInvarient () o ToLowerInvarient () nel codice o nella query e queste 4 funzioni hanno benchmark di prestazioni diversi. Vedi le regole di prestazione di Microsoft su questo. (esecuzione dell'applicazione)

2- L'utilizzo di surrogate int garantisce di non modificare la chiave nel tempo. Anche i codici Paese possono cambiare, vedi Wikipedia come i codici ISO sono cambiati nel tempo. Ci vorrebbe molto tempo per cambiare la chiave primaria per i sottotitoli. (esecuzione del mantenimento dei dati)

3- Sembra che ci siano problemi con le soluzioni ORM, come NHibernate quando PK / FK non è int. (prestazioni dello sviluppatore)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.