Benötigen diese speziellen Tabellen Ersatzschlüssel?

13

Hintergrund

Ich habe diese Tische

+-------------------------+  +------------------------+
|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 ist der IATA (International Air Transport Association) Flughafen - Code , können Sie sie in Ihrem Gepäck - Tags sehen , wenn Sie mit dem Flugzeug reisen.

Bildbeschreibung hier eingeben

country_code ist der ISO 3166-1 A3-Standard-Ländercode , den Sie bei den Olympischen Spielen sehen können.

Bildbeschreibung hier eingeben

currency_code ist der IS0 417-Standardwährungscode (3 Zeichen) , der auf Anzeigetafeln für internationale Wechselkurse angezeigt wird.

Bildbeschreibung hier eingeben

Fragen

Sind diese natürlichen PKs gut genug?

Ist die Verwendung von weltweit anerkannten Standards, die von der gesamten Branche akzeptiert werden, gut genug für PKs?

Benötigen diese Tabellen Ersatz, egal was passiert?

Tulains Córdova
quelle

Antworten:

15

Nein, das tun sie nicht. Diese Schlüssel sind definitiv gut genug!

Sie sind einzigartig, werden sich nicht selten ändern und sind aussagekräftig , was einen Schritt über einen Ersatzschlüssel darstellt. Das ist so ziemlich die Definition einer guten PK.

Die Einschränkungen bezüglich unveränderlicher PKs und numerischer Ganzzahlen sind nicht Teil des relationalen Modells (Codds) oder eines SQL-Standards (ANSI oder andere).

Bobson
quelle
3
Primärschlüssel müssen ebenfalls unveränderlich sein, was IATA-Flughafencodes definitiv nicht sind. Sie können nach Belieben der IATA geändert werden.
James Snell
3
@JamesSnell - IATA-Flughafencodes sind ungefähr so ​​unveränderlich wie Ländercodes. Sie sprechen vielleicht alle zehn Jahre von einer Veränderung . Siehe hier für eine Diskussion der Angelegenheit. Es gibt viele veraltete Codes, die noch vorhanden sind, weil sie zu schwer zu ändern sind. Darüber hinaus ist dies ein CASCADE-Update. Veränderbare Primärschlüssel sind legitim, wenn nicht sogar großartige Methoden.
Bobson
2
@EricKing Diese 3. Partei setzt sich zufällig aus Vertretern aller wichtigen Parteien vieler Branchen zusammen, dann werden die Standards jahrelang diskutiert und dann abgestimmt, bis ein vernünftiger Konsens erreicht ist. Sie einigen sich auch auf die Mechanismen, durch die Änderungen oder neue Ergänzungen vorgenommen werden. Außerdem werden die Codelisten-Standards nicht aus einer Laune heraus erstellt, sondern weil die Notwendigkeit besteht, eine kontrollierte, respektierte, vereinbarte Codeliste für etwas zu erstellen, um weltweit zusammenarbeiten und weltweit ordnungsgemäß kommunizieren zu können.
Tulains Córdova
2
@ user61852 - Sie könnten diese Standards sagen sind gemacht Primärschlüssel zu sein.
Bobson
3
@ Bobson: "Es gibt viele veraltete Codes, die noch vorhanden sind, weil sie zu schwer zu ändern sind" -> möglicherweise, weil sie Primärschlüssel sind?
Maciej
2

Ich denke, Need ist ein sehr starkes Wort, und im engeren Sinne benötigen die Tabellen wahrscheinlich keine Ersatzschlüssel .

Wenn es jedoch meine Datenbank wäre, würde ich wahrscheinlich sowieso Ersatzschlüssel hinzufügen. Ich möchte nicht unbedingt, dass mein Datenbankdesign von einer Reihe von Drittanbietern (IATA, ISO) abhängt, unabhängig davon, wie stabil ihre Standards sind. Oder ich möchte mich überhaupt nicht auf einen bestimmten Standard verlassen (gibt es andere Währungscode-Standards? Ich weiß nicht). Ich würde wahrscheinlich meine Tabellen mit Ersatzschlüsseln wie folgt modellieren:

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

Mit anderen Worten, wenn diese Industriestandardcodes für meine Anwendung nicht von Natur aus wichtig sind, würde ich sie nicht als PK meiner Tabellen verwenden. Sie sind nur Etiketten. Die meisten meiner anderen Tabellen werden wahrscheinlich sowieso Ersatzschlüssel haben, und dieses Setup würde meinem Datenmodell mehr Konsistenz verleihen. Die Kosten für das Hinzufügen der Ersatzschlüssel sind minimal.

Update basierend auf einigen Kommentaren:

Ohne den Kontext der Beispieltabellen zu kennen, ist es unmöglich zu wissen, wie wichtig Dinge wie IATA-Flughafencodes für die Anwendung sind, die die Datenbank verwendet. Wenn IATA-Codes für die gesamte Anwendung von zentraler Bedeutung sind und überall in der Anwendung verwendet werden, ist es möglicherweise die richtige Entscheidung, die Codes nach ordnungsgemäßer Analyse als PK der Tabelle zu verwenden.

Wenn es sich bei der Tabelle jedoch nur um eine Lookup-Tabelle handelt, die in einigen Ecken der App verwendet wird, rechtfertigt die relative Bedeutung der IATA-Codes möglicherweise keinen so wichtigen Punkt in der Datenbankinfrastruktur. Sicher, Sie müssen hier und da ein paar Abfragen zusätzlich mitmachen, aber dieser Aufwand ist möglicherweise trivial im Vergleich zu dem Aufwand, der erforderlich ist, um sicherzustellen, dass Sie die Auswirkungen der IATA-Codes vollständig verstehen Primärschlüsselfeld. In einigen Fällen ist es mir nicht nur egal, sondern ich möchte mich auch nicht um die IATA-Codes kümmern müssen . Der folgende Kommentar von @James Snell ist ein perfektes Beispiel für etwas, über das ich mir keine Sorgen machen möchte, wenn es um die Beeinflussung der PK meiner Tabellen geht.

Auch die Konsistenz im Design ist wichtig. Wenn Sie eine Datenbank mit Dutzenden von Tabellen haben, die alle konsistent Ersatzschlüssel entworfen haben, und dann ein paar Nachschlagetabellen, die Codes von Drittanbietern als PK verwenden, führt dies zu einer Inkonsistenz. Das ist nicht ganz schlecht, erfordert aber zusätzliche Aufmerksamkeit bei der Dokumentation und solche, die möglicherweise nicht gerechtfertigt sind. Es handelt sich um Nachschlagetabellen , nur einen Ersatzschlüssel für die Konsistenz zu verwenden, ist vollkommen in Ordnung.

Update basierend auf weiteren Recherchen:

Ok, die Neugier hat mich gebissen und ich habe mich aus Spaß dazu entschlossen, nach IATA-Flughafencodes zu suchen, beginnend mit den in der Frage angegebenen Links.

Wie sich herausstellt, sind die IATA-Codes nicht so universell und maßgeblich, wie es die Frage vermuten lässt. Nach dieser Seite :

Die meisten Länder verwenden in ihren offiziellen Luftfahrtveröffentlichungen vierstellige ICAO-Codes und keine IATA-Codes.

Darüber hinaus unterscheiden sich IATA- und ICAO-Codes von FAA-Identifizierungscodes , die eine weitere Möglichkeit zur Identifizierung von Flugplätzen darstellen.

Ich möchte damit nicht eine Debatte darüber beginnen, welche Codes besser oder universeller oder autorisierender oder umfassender sind, sondern genau zeigen, warum das Entwerfen Ihrer Datenbankstruktur anhand einer willkürlichen Drittanbieter-ID nicht meine Absicht ist , es sei denn, es gab einen bestimmten geschäftlichen Grund dafür .

In diesem Fall fühle ich meine Datenbank besser strukturiert, stabiler werden würde, und flexibler zu gestalten, indem sie die IATA - Codes zu verzichten (oder eine dritte Partei, potentiell veränderbare Code) als Primärschlüssel Kandidaten und verwenden Sie einen Ersatzschlüssel. Auf diese Weise kann ich auf potenzielle Fallstricke verzichten, die durch die Auswahl des Primärschlüssels entstehen könnten.

Eric King
quelle
1
Die IATA-Standards sind also gut genug für Fluggesellschaften, aber nicht für Sie?
Tulains Córdova
1
Natürlich müssen Sie sich bis an den Flughafentisch begeben, wenn Sie nach Gepäckstücken aus London Heathrow suchen möchten, da dies nicht möglich ist. Dies select * from baggage where airport_code = 'LHR'bedeutet, dass die Datenbank nur über die Anwendung verwendet werden kann, die sehr eng und proprietär ist Ansatz, insbesondere wenn der Geschäftsinhaber derjenige ist, der für die Datenbank bezahlt hat und sie daher besitzt. Außerdem müssen Sie Code schreiben, um alltägliche Dinge wie das Importieren von Daten aus einer Datenbank in eine andere zu erledigen, um PK-Kollisionen zu vermeiden.
Tulains Córdova
1
IATA-Codes sind nicht unveränderlich und können daher nicht als PK-Kandidaten betrachtet werden. Beispiel: Der Code IDL befand sich in New York, bis er in JFK umbenannt wurde. Der IDL-Code befindet sich jetzt in Mississippi.
James Snell
2
@EricKing IATA und ISO sorgen dafür, dass die Codes stabil genug, einzigartig und allgemein akzeptiert sind. Das hängt sehr mit dem Interesse einer Person zusammen, die einen Tisch entwirft.
Tulains Córdova
2
@ user61852 - Nur weil dies Standardcodes sind, bedeutet dies nicht, dass das Airline-System sie als PKs verwendet (vielleicht haben Sie hier mehr Einblick?). Ein so umfangreiches Update zu haben, scheint eine sehr schlechte Idee zu sein.
JeffO
1

Während es in Ordnung ist, Ersatzschlüssel in den Feldern zu haben, ist daran nichts auszusetzen, was zu berücksichtigen ist, könnte die Größe der Indexseite selbst sein.

Da es sich um eine relationale Datenbank handelt, werden Sie eine Menge Verknüpfungen durchführen. Wenn Sie einen Ersatzschlüssel eines numerischen Typs verwenden, ist die Datenbank möglicherweise einfacher zu handhaben, dh die Indexseitengröße ist kleiner und die Suche kann schneller durchgeführt werden. Wenn es sich um ein kleines Projekt handelt, spielt es keine Rolle und Sie kommen problemlos zurecht. Je größer die Anwendung, desto mehr möchten Sie Engpässe reduzieren.

Wenn Sie einen BIGINT-, INT-, SMALLINT-, TINYINT- oder einen ganzzahligen Datentyp haben, können Sie sich später Probleme ersparen.

Nur meine 2 Cent

AKTUALISIEREN:

Kleines Projekt - von ein paar, vielleicht sogar ein paar Dutzend Leuten genutzt. Kleines Demoprojekt, Projekt für den persönlichen Gebrauch, etwas, das einem Portfolio hinzugefügt werden kann, wenn Sie Ihre Fähigkeiten ohne Erfahrung präsentieren, und dergleichen.

Großes Projekt - wird täglich von Tausenden, Zehntausenden und Millionen Benutzern verwendet. Etwas, das Sie für ein nationales / internationales Unternehmen mit einer riesigen Anwenderbasis aufbauen würden.

In der Regel werden nur einige wenige Datensätze häufig ausgewählt, und der Server speichert die Ergebnisse für einen schnellen Zugriff im Cache. Von Zeit zu Zeit müssen Sie jedoch auf einige weniger genutzte Datensätze zugreifen. Zu diesem Zeitpunkt müsste der Server in den Index eintauchen Seite. (im obigen Beispiel mit den Flughafennamen fliegen die Leute oft inländische Fluggesellschaften, sagen wir Chichago -> Los Angeles, aber wie oft fliegen die Leute von Boston -> Simbabwe)

Wenn VARCHAR verwendet wird, bedeutet dies, dass der Abstand nicht einheitlich ist, es sei denn, die Daten sind immer gleich lang (an diesem Punkt ist ein CHAR-Wert effektiver). Dadurch wird das Durchsuchen des Index langsamer, und da der Server bereits mit Tausenden und Abertausenden von Abfragen pro Sekunde beschäftigt ist, muss er Zeit für das Durchsuchen eines nicht einheitlichen Index verschwenden und das Gleiche bei den Verknüpfungen wiederholen (was langsamer ist als reguläre Auswahlen in einer nicht optimierten Tabelle, z. B. DW, wo es so wenig Verknüpfungen wie möglich gibt, um das Abrufen von Daten zu beschleunigen). Auch wenn Sie UTF verwenden, kann das ebenfalls mit dem Datenbankmodul zu Problemen führen (ich habe einige Fälle gesehen).

Persönlich kann ein ordnungsgemäß organisierter Index meiner Erfahrung nach die Geschwindigkeit eines Joins um ~ 70% erhöhen, und das Durchführen eines Joins für eine Ganzzahlspalte kann den Join um bis zu ~ 25% beschleunigen (abhängig von den Daten). . Wenn die Haupttabellen zu wachsen beginnen und diese Tabellen verwendet werden, sollten Sie lieber einen Integer-Datentyp in der Spalte mit ein paar Bytes verwenden, als ein VARCHAR / CHAR-Feld, das mehr Platz einnimmt. Es geht darum, Speicherplatz zu sparen, die Leistung zu steigern und die Gesamtstruktur einer relationalen Datenbank zu verbessern.

Auch, wie James Snell erwähnte:

Primärschlüssel müssen ebenfalls unveränderlich sein, was IATA-Flughafencodes definitiv nicht sind. Sie können nach Belieben der IATA geändert werden.

Wenn Sie dies berücksichtigen, müssen Sie eher 1 Datensatz aktualisieren, der an eine Zahl gebunden ist, als dass Sie diesen einen Datensatz plus alle Datensätze in der Tabelle, zu der Sie beitreten, aktualisieren müssen.

Toni Kostelac
quelle
Es ist ein gültiger Gedanke, aber der Sinn dieser Tabellen ist, dass es in jeder Tabelle nur eine begrenzte Anzahl von Datensätzen gibt. Wenn Sie tatsächlich Codegröße gemeint durch small projectund biggeraktualisieren Sie bitte zu klären , warum die Materie würde.
Bobson
1
Die Einschränkungen bezüglich unveränderlicher PKs und numerischer Ganzzahlen sind nicht Teil des relationalen Modells (Codds) oder eines SQL-Standards (ANSI oder andere).
Tulains Córdova
4
Indizes, die auf kurzen Zeichenfolgen mit fester Länge (wie ISO-Codes) basieren, sind so schnell wie ganze Zahlen. Indizes, die auf variabler Länge basieren, sind lange Strings nicht.
Tulains Córdova
Das ist, was ich gesagt habe (siehe den obigen Teil VARCHAR vs CHAR). Ich hatte keine Chance, einen kurzen String mit fester Länge gegen eine numerische Ganzzahl zu testen, aber ich hatte die Chance, dies mit einer variablen Länge und einer Ganzzahl zu tun
Toni Kostelac
2
Join Performance ist ein Strohmann. Wenn Sie natürliche Schlüssel verwenden, müssen Sie häufig erst keinen Join erstellen.
Mike Sherrill "Cat Recall"
1

Wenn Sie den Ansatz "Ich verwende ständig Ersatzschlüssel" wählen, können Sie diese Art von Bedenken umgehen. Das mag nicht gut sein, da es wichtig ist, über Ihre Daten nachzudenken, aber es spart sicherlich viel Zeit, Energie und Mühe. Wenn irgendjemand diese Regel akzeptieren würde, wären die aufgelisteten Beispiele mit Sicherheit geeignet, da die Änderung nur in einem "Akt des Kongresses" durchgeführt werden kann.

Ad-hoc-Abfragen einer Datenbank mit diesen natürlichen Schlüsseln sind sicherlich hilfreich. Das Erstellen von Ansichten, die dasselbe tun, indem sie die Nachschlagetabellen einschließen, kann genauso gut funktionieren. Moderne Datenbanken machen mit solchen Dingen einen viel besseren Job, bis es wahrscheinlich egal ist.

Es gibt einige spezifische Fälle in den USA, in denen die Standards drastisch geändert wurden: Die Postleitzahl wurde von 5 bis 9 Ziffern erweitert, die Abkürzungen der Bundesstaaten wurden zu konsistenten 2 Buchstaben Die Welt muss sich mit Y2K auseinandersetzen. Wenn Sie eine Echtzeit-App mit Daten haben, die auf der ganzen Welt verteilt sind und Milliarden von Datensätzen enthalten, sind kaskadierende Aktualisierungen nicht die beste Idee. Sollten wir nicht alle an Orten arbeiten, an denen solche Herausforderungen auftreten? Mit diesem Datensatz können Sie es selbst testen und eine differenziertere Antwort finden.

JeffO
quelle
+1 Gute Antwort. Meistens sind die Leute in dieser Frage sehr dogmatisch. Viele Datenbankdesigner haben ein riesiges Ego und betrachten sich als Eigentümer der Datenbank und der Daten. Andere sehen OK, dass der Eigentümer der Daten sie nur über eine bestimmte Anwendung verwenden kann, weil er keinen Sinn daraus ziehen kann. Sie ziehen es auch vor, Vorkehrungen für etwas zu treffen, das möglicherweise in der Zukunft passiert oder nicht, während sie die Dinge, die täglich erledigt werden, wie das Importieren von Daten und das Schreiben von Abfragen, zur Hölle machen. Es ist auch nicht möglich, irgendeine Art von kanonischer Bibliographie zu erstellen, die ihre Sichtweise unterstützt.
Tulains Córdova
Übrigens ist die Regel "Ich verwende die ganze Zeit Ersatzschlüssel" weder im relationalen Modell (Codd's) noch in einem SQL-Standard enthalten. Das Oracle Data Dictionary-Schema verwendet nach Möglichkeit natürliche Schlüssel und in den anderen Fällen künstliche Schlüssel. PPDM ( ppdm.org ) empfiehlt ebenfalls den gemischten Ansatz und verwendet ihn in seinem Modell. ANSI SQL Standard sagt nichts über All-Surrogates aus. Ich denke, All-Surrogate und All-Natural sind ätzend. Einige natürliche und einige Ersatz sind das, was das relationale Modell lehrt.
Tulains Córdova