Queste tabelle specifiche richiedono chiavi surrogate?


13

sfondo

Ho queste tabelle

+-------------------------+  +------------------------+
|Airport                  |  |Country                 |
|-------------------------|  |------------------------|
|airport_code string (PK) |  |country_code string (PK)|
|address string           |  |name string             |
|name  string             |  +------------------------+
+-------------------------+

+-------------------------+
|Currency                 |
|-------------------------|
|currency_code string (PK)|
|name string              |
+-------------------------+

airport_code è il codice aeroportuale IATA (International Air Transport Association) , puoi vederlo nelle etichette dei bagagli quando viaggi in aereo.

inserisci qui la descrizione dell'immagine

country_code è il codice ISO standard ISO 3166-1 A3 , puoi vederlo nelle olimpiadi.

inserisci qui la descrizione dell'immagine

currency_code è il codice valuta IS0 417 standard a 3 caratteri , puoi vederli nei tabelloni internazionali di cambio valuta.

inserisci qui la descrizione dell'immagine

Domande

Questi PK naturali sono abbastanza buoni?

L'uso degli standard mondiali rispettati, che sono accettati da intere industrie abbastanza bene per i PK?

Queste tabelle hanno bisogno di surrogati, non importa cosa?

Risposte:


15

No, non lo fanno. Quelle chiavi sono decisamente abbastanza buone!

Sono unici, non raramente cambieranno e significativi , il che è un passo avanti rispetto a una chiave surrogata. Questa è praticamente la definizione di un buon PK.

Le restrizioni sul fatto che i PK siano immutabili e numeri interi non fanno parte del Modello relazionale (Codd's) o di qualsiasi standard SQL (ANSI o altro).


3
Le chiavi primarie devono anche essere immutabili, qualcosa che i codici aeroportuali IATA sicuramente non lo sono. Possono essere cambiati per capriccio della IATA.
James Snell,

3
@JamesSnell - I codici aeroportuali IATA sono immutabili quanto i codici paese. Stai parlando di un cambiamento forse una volta ogni decennio, se quello. Vedi qui per una discussione della questione. Ci sono molti codici obsoleti che sono ancora in atto perché sono troppi problemi da cambiare. Inoltre, ecco a cosa serve un aggiornamento CASCADE. Le chiavi primarie mutabili sono legittime, se non una buona pratica.
Bobson,

2
@EricKing Queste terze parti sono composte da rappresentanti di tutte le principali parti di molti settori, quindi gli standard vengono discussi per anni, quindi votati fino a raggiungere un ragionevole consenso. Inoltre concordano i meccanismi attraverso i quali vengono apportate modifiche o nuove aggiunte. Oltre a ciò, gli standard delle liste di codici vengono creati, non per un capriccio, ma perché esiste la necessità di creare un elenco di codici controllato, rispettato, concordato per qualcosa, al fine di essere in grado di interagire in tutto il mondo e comunicare correttamente in tutto il mondo.
Tulains Córdova,

2
@ user61852 - Si potrebbe dire che questi standard sono fatti come chiavi primarie.
Bobson,

3
@Bobson: "Ci sono molti codici obsoleti che sono ancora in atto perché sono troppi problemi da cambiare" -> forse perché sono chiavi primarie?
Maciej,

2

Penso che bisogno sia una parola molto forte e, in senso stretto, i tavoli probabilmente non hanno bisogno di chiavi surrogate .

Tuttavia, se fosse il mio database, probabilmente aggiungerei comunque le chiavi surrogate. Potrei non voler necessariamente che il mio progetto di database dipenda da un gruppo di terze parti (IATA, ISO), indipendentemente da quanto siano stabili i loro standard. Oppure, potrei non voler dipendere da un particolare standard (ci sono altri standard di codice valuta? Non lo so). Probabilmente modellerei le mie tabelle con chiavi surrogate in questo modo:

+-------------------------+  +------------------------+
|Airport                  |  |Country                 |
|-------------------------|  |------------------------|
|airport_id       int (PK)|  |country_id     int (PK) |
|iata_airport_code string |  |iso_country_code string |
|icao_airport_code string |  +------------------------+
|faa_identifier    string |  
|address           string |  
|name              string |  
+-------------------------+

+-------------------------+
|Currency                 |
|-------------------------|
|currency_id int (PK)     |
|iso_currency_code string |
|name string              |
+-------------------------+

In altre parole, a meno che quei codici standard del settore non siano intrinsecamente importanti per la mia applicazione, non li userei come PK delle mie tabelle. Sono solo etichette. La maggior parte delle altre mie tabelle avrà probabilmente chiavi surrogate comunque, e questa configurazione aggiungerebbe coerenza al mio modello di dati. Il costo dell '"aggiunta" delle chiavi surrogate è minimo.

Aggiornamento basato su alcuni dei commenti:

Senza conoscere il contesto delle tabelle di esempio, è impossibile sapere quanto importanti siano i codici aeroportuali IATA per l'applicazione che utilizza il database. Ovviamente, se i codici IATA sono di importanza centrale e utilizzati in modo pervasivo in tutta l'applicazione, potrebbe essere la decisione corretta, dopo un'analisi adeguata, di utilizzare i codici come PK della tabella.

Tuttavia, se la tabella è solo una tabella di ricerca utilizzata in alcuni angoli dell'app, l'importanza relativa dei codici IATA potrebbe non giustificare un punto così importante nell'infrastruttura del database. Certo, potresti dover fare un ulteriore join in alcune query qua e là, ma tale sforzo potrebbe essere banale rispetto allo sforzo che ci vorrebbe per fare la ricerca per assicurarti di comprendere appieno le implicazioni del rendere i codici IATA il campo chiave primaria. In alcuni casi, non solo non mi interessa, ma non voglio preoccuparmi dei codici IATA. Il commento di @James Snell qui sotto è un perfetto esempio di qualcosa che non potrei voler preoccuparmi di influenzare il PK dei miei tavoli.

Inoltre, la coerenza nel design è importante. Se si dispone di un database con decine di tabelle che hanno tutte chiavi surrogate progettate in modo coerente e quindi alcune tabelle di ricerca che utilizzano codici di terze parti come PK, ciò introduce un'incoerenza. Non è del tutto negativo, ma richiede un'attenzione particolare nella documentazione e tale che potrebbe non essere giustificato. Sono tabelle di ricerca per l'amor del cielo, solo usare una chiave surrogata per coerenza va benissimo.

Aggiornamento basato su ulteriori ricerche:

Ok, la curiosità mi ha morso e ho deciso di fare qualche ricerca sui codici aeroportuali IATA per divertimento, a partire dai link forniti nella domanda.

A quanto pare, i codici IATA non sono così universali e autorevoli come la domanda li rende. Secondo questa pagina :

La maggior parte dei paesi utilizza codici ICAO a quattro caratteri , non codici IATA, nelle loro pubblicazioni aeronautiche ufficiali.

Inoltre, i codici IATA e ICAO sono distinti dai codici identificativi FAA , che rappresentano ancora un altro modo per identificare i campi di aviazione.

Il mio punto di vista non è quello di iniziare un dibattito su quali codici siano migliori o più universali o più autorevoli o più completi, ma mostrare esattamente perché progettare la struttura del database attorno a un identificatore di terze parti arbitrario non è qualcosa che sceglierei di fare , a meno che non vi fosse un motivo commerciale specifico per farlo .

In questo caso, ritengo che il mio database sarebbe meglio strutturato, più stabile e più flessibile, rinunciando ai codici IATA (o qualsiasi codice di terze parti, potenzialmente modificabile) come candidato chiave principale e usando una chiave surrogata. In questo modo, posso rinunciare a eventuali insidie ​​che potrebbero sorgere a causa della selezione della chiave primaria.


1
Quindi gli standard IATA sono abbastanza buoni per le compagnie aeree ma non per te?
Tulains Córdova,

1
Ovviamente dovrai unirti fino al tavolo dell'aeroporto quando vuoi cercare un bagaglio da Londra Heathrow, perché non puoi farlo select * from baggage where airport_code = 'LHR', il che significa che il database è utilizzabile solo per lanciare l'applicazione, che è molto stretta e proprietaria approccio, specialmente quando l'imprenditore è colui che ha pagato il database e quindi lo possiede. Inoltre dovrai scrivere codice per fare cose banali come importare dati da un database a un altro per evitare le collisioni PK.
Tulains Córdova,

1
I codici IATA non sono immutabili quindi non possono essere considerati candidati PK. Esempio: il codice IDL era a New York, fino a quando non è stato ribattezzato JFK. Il codice IDL è ora in Mississippi.
James Snell,

2
@EricKing IATA e ISO si preoccupano che i codici siano abbastanza stabili, unici e universalmente accettati. Ciò coincide molto con l'interesse di una persona a progettare un tavolo.
Tulains Córdova,

2
@ user61852 - solo perché questi sono codici standard non significa che il sistema aereo li usi come PK (forse hai più informazioni qui?). Avere un aggiornamento a cascata su così vasta scala sembra una pessima idea.
JeffO

1

Avere chiavi surrogate sui campi va bene e non c'è nulla di sbagliato in ciò che qualcosa da considerare potrebbe essere la dimensione della pagina dell'indice stessa.

Dato che si tratta di un database relazionale, farai molti join e avere una chiave surrogata di tipo numerico potrebbe semplificare la gestione del database, ad esempio le dimensioni della pagina dell'indice saranno più piccole e quindi più veloci nella ricerca. Se questo è un piccolo progetto, non importa e ci riuscirai senza problemi, tuttavia più grande diventa l'applicazione, più vorrai ridurre i colli di bottiglia.

Avere un BIGINT, INT, SMALLINT, TINYINT o qualsiasi tipo di dati di tipo intero può farti risparmiare qualche problema.

Solo i miei 2 centesimi

AGGIORNARE:

Piccolo progetto - usato da poche, forse anche poche decine di persone. Piccola scala, progetto dimostrativo, progetto per uso personale, qualcosa da aggiungere a un portfolio quando si presentano le tue abilità senza esperienza e simili.

Grande progetto - utilizzato da migliaia, decine di migliaia, milioni di utenti ogni giorno. Qualcosa che costruiresti per un'azienda nazionale / internazionale con una vasta base di utenti.

Di solito ciò che accade è che alcuni dei record vengono selezionati spesso e il server memorizza nella cache i risultati per un accesso rapido, ma di tanto in tanto è necessario accedere ad alcuni record meno utilizzati, a quel punto il server dovrebbe immergersi nell'indice pagina. (nell'esempio sopra con i nomi degli aeroporti, le persone spesso volano con compagnie aeree nazionali, ad esempio Chichago -> Los Angeles, ma con quale frequenza le persone volano da Boston -> Zimbabwe)

Se si utilizza VARCHAR significa che la spaziatura non è uniforme, a meno che i dati abbiano sempre la stessa lunghezza (a quel punto un valore CHAR è più efficace). Ciò rende più lenta la ricerca dell'indice e, poiché il server è già occupato a gestire migliaia e migliaia di query al secondo, ora deve perdere tempo a passare attraverso un indice non uniforme e fare di nuovo la stessa cosa sui join (che è più lento di seleziona regolarmente su una tabella non ottimizzata, prendi DW come esempio dove ci sono meno join possibili per accelerare il recupero dei dati). Anche se usi UTF che può anche pasticciare con il motore di database (ho visto alcuni casi).

Personalmente, per esperienza personale, un indice adeguatamente organizzato può aumentare la velocità di un join di circa il 70% e fare un join su una colonna intera può accelerare il join di circa il 25% circa (a seconda dei dati) . Man mano che le tabelle principali iniziano a crescere e queste tabelle vengono utilizzate su di esse, preferiresti che un tipo di dati intero occupi la colonna che ha alcuni byte rispetto a un campo VARCHAR / CHAR che occuperà più spazio. Si tratta di risparmiare spazio su disco, aumentare le prestazioni e la struttura generale di un database relazionale.

Inoltre, come menzionato da James Snell:

Le chiavi primarie devono anche essere immutabili, qualcosa che i codici aeroportuali IATA sicuramente non lo sono. Possono essere cambiati per capriccio della IATA.

Quindi, tenendo conto di questo, preferiresti aggiornare 1 record associato a un numero, invece di dover aggiornare quel record più tutti i record nella tabella a cui ti unisci.


È un pensiero valido, ma il punto di queste tabelle è che ci sono solo una quantità finita di record in ogni tabella. Se in realtà intendevi la dimensione del codice per small projecte bigger, ti preghiamo di aggiornare per chiarire perché ciò avrebbe importanza.
Bobson,

1
Le restrizioni sul fatto che i PK siano immutabili e numeri interi non fanno parte del Modello relazionale (Codd's) o di qualsiasi standard SQL (ANSI o altro).
Tulains Córdova,

4
Gli indici basati su lunghezza fissa, stringhe corte (come i codici ISO) sono veloci quanto gli interi. Gli indici basati su lunghezza variabile, stringhe lunghe non lo sono.
Tulains Córdova,

Questo è quello che ho affermato (vedi la parte VARCHAR vs CHAR sopra) non ho avuto la possibilità di testare una stringa corta a lunghezza fissa vs un numero intero, ma ho avuto la possibilità di farlo con una lunghezza variabile e un numero intero
Toni Kostelac,

2
Unisciti alla performance è un uomo di paglia. Spesso, l'utilizzo di chiavi naturali significa che non è necessario in primo luogo un join.
Mike Sherrill "Cat Recall",

1

Se segui l'approccio "Uso sempre chiavi surrogate", puoi evitare questo tipo di preoccupazione. Potrebbe non essere una buona cosa perché è importante riflettere sui tuoi dati, ma sicuramente fa risparmiare un sacco di tempo, energie e sforzi. Se qualcuno dovesse adottare un'accettazione a questa regola, gli esempi elencati si qualificheranno sicuramente perché ci vuole un quasi "atto congressuale" per apportare il cambiamento.

Le query ad hoc di un database con queste chiavi naturali sono sicuramente utili. La creazione di viste che fanno la stessa cosa includendo le tabelle di ricerca può funzionare altrettanto bene. I database moderni fanno un lavoro molto migliore con questo tipo di cose al punto che probabilmente non importa.

Ci sono alcuni casi specifici negli Stati Uniti, in cui gli standard sono stati drasticamente cambiati: il codice postale si è espanso da 5 a 9 cifre, le abbreviazioni dello stato a 2 lettere coerenti e si sbarazzano del periodo (ricordi quando l'Illinois era malato? il mondo ha avuto a che fare con Y2K. Se disponi di un'app in tempo reale con dati diffusi in tutto il mondo contenenti miliardi di record, gli aggiornamenti a cascata non sono l'idea migliore, ma non dovremmo tutti lavorare in luoghi che affrontano tali sfide? Con quel set di dati, potresti testarlo tu stesso e trovare una risposta più diffinativa.


+1 Ottima risposta. Il più delle volte le persone sono molto dogmatiche su questo tema. Molti progettisti di database hanno un ego gigantesco e si considerano i proprietari del database e dei dati. Altri vedono bene che il proprietario dei dati può usarli solo attraverso un'applicazione specifica, perché non può capirne il significato. Preferiscono anche fare disposizioni per qualcosa che potrebbe o non potrebbe accadere in futuro, mentre fanno un inferno vivente di cose che vengono fatte su base giornaliera come l'importazione di dati e la scrittura di query. Inoltre, non riesce a produrre alcun tipo di bibliografia canonica che supporti la loro visione.
Tulains Córdova,

A proposito, la regola "Uso sempre chiavi surrogate" non è nel Modello relazionale (Codd's) né in alcuno standard SQL. Lo schema del dizionario dei dati Oracle utilizza chiavi naturali quando possibile e chiavi artificiali nelle altre istanze. PPDM ( ppdm.org ) raccomanda anche l'approccio misto e lo usa nel suo modello. ANSI SQL Standard non dice nulla su tutti i surrogati. Penso che tutti i surrogati e tutto naturali siano corrosivi. Qualche naturale e un surrogato è ciò che insegna il modello relazionale.
Tulains Córdova,
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.