Ces tables spécifiques nécessitent-elles des clés de substitution?

13

Contexte

J'ai ces tables

+-------------------------+  +------------------------+
|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 est le code d'aéroport IATA (International Air Transport Association) , vous pouvez les voir dans vos étiquettes à bagages lorsque vous voyagez en avion.

entrez la description de l'image ici

country_code est le code de pays standard ISO 3166-1 A3 , vous pouvez les voir aux Jeux olympiques.

entrez la description de l'image ici

currency_code est le code de devise standard à 3 caractères IS0 417 , vous pouvez les voir dans les panneaux d'affichage de change international.

entrez la description de l'image ici

Des questions

Ces PK naturels sont-ils assez bons?

L'utilisation de normes respectées dans le monde entier, acceptées par des industries entières, est-elle suffisamment bonne pour les PK?

Ces tables ont-elles besoin de substituts quoi qu'il arrive?

Tulains Córdova
la source

Réponses:

15

Non, ils ne le font pas. Ces clés sont vraiment assez bonnes!

Ils sont uniques, ne changeront pas rarement et sont significatifs , ce qui est un pas en avant par rapport à une clé de substitution. C'est à peu près la définition d'un bon PK.

Les restrictions concernant les PK immuables et les entiers numériques ne font pas partie du modèle relationnel (Codd) ou de toute norme SQL (ANSI ou autre).

Bobson
la source
3
Les clés primaires doivent également être immuables, contrairement aux codes d'aéroport IATA. Ils peuvent être modifiés au gré de l'IATA.
James Snell
3
@JamesSnell - Les codes d'aéroport IATA sont à peu près aussi immuables que les codes de pays. Vous parlez d'un changement peut-être une fois tous les dix ans, si cela. Voir ici pour une discussion de la question. Il y a beaucoup de codes obsolètes qui sont toujours en place car ils sont trop difficiles à changer. De plus, c'est à cela que sert une mise à jour CASCADE. Les clés primaires mutables sont légitimes, sinon une bonne pratique.
Bobson
2
@EricKing Ces tierces parties sont composées de représentants de tous les principaux partis de nombreuses industries, puis les normes sont discutées pendant des années, puis votées jusqu'à ce qu'un consensus raisonnable soit atteint. Ils conviennent également des mécanismes par lesquels tout changement ou nouvel ajout est effectué. En plus de cela, les normes de listes de codes sont créées, non pas sur un coup de tête, mais parce qu'il existe un besoin de créer une liste de codes contrôlée, respectée et convenue pour quelque chose, afin de pouvoir interopérer dans le monde entier et communiquer correctement dans le monde entier.
Tulains Córdova
2
@ user61852 - On pourrait dire que ces normes sont faites pour être des clés primaires.
Bobson
3
@Bobson: "Il y a beaucoup de codes obsolètes qui sont toujours en place parce qu'ils sont trop difficiles à changer" -> peut-être parce que ce sont des clés primaires?
Maciej
2

Je pense que le besoin est un mot très fort, et au sens strict, les tables n'ont probablement pas besoin de clés de substitution .

Cependant, si c'était ma base de données, j'ajouterais probablement des clés de substitution de toute façon. Je ne veux pas nécessairement que ma conception de base de données dépende d'un tas de tiers (IATA, ISO), quelle que soit la stabilité de leurs normes. Ou, je ne veux pas du tout dépendre d'une norme particulière (existe-t-il d'autres normes de code de devise? Je ne sais pas). Je modéliserais probablement mes tables avec des clés de substitution comme ceci:

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

En d'autres termes, à moins que ces codes standard de l'industrie ne soient intrinsèquement importants pour mon application, je ne les utiliserais pas comme PK de mes tables. Ce ne sont que des étiquettes. La plupart de mes autres tables auront probablement des clés de substitution de toute façon, et cette configuration ajouterait de la cohérence à mon modèle de données. Le coût de «l'ajout» des clés de substitution est minime.

Mise à jour basée sur certains des commentaires:

Sans connaître le contexte des exemples de tableaux, il est impossible de savoir à quel point des éléments tels que les codes d'aéroport IATA sont importants pour l'application utilisant la base de données. De toute évidence, si les codes IATA sont d'une importance centrale et utilisés de manière omniprésente dans l'application, il pourrait être la bonne décision, après une analyse appropriée, d'utiliser les codes comme PK de la table.

Cependant, si la table est juste une table de recherche utilisée dans quelques coins de l'application, l'importance relative des codes IATA peut ne pas justifier une place aussi importante dans l'infrastructure de la base de données. Bien sûr, vous devrez peut-être faire une jointure supplémentaire dans quelques requêtes ici et là, mais cet effort pourrait être trivial par rapport à l'effort qu'il faudrait pour faire la recherche pour vous assurer de bien comprendre les implications de faire des codes IATA le champ de clé primaire. Dans certains cas, non seulement je m'en fiche, mais je ne veux pas me soucier des codes IATA. Le commentaire de @James Snell ci-dessous est un exemple parfait de quelque chose que je ne voudrais peut-être pas avoir à craindre d'affecter le PK de mes tables.

En outre, la cohérence de la conception est importante. Si vous avez une base de données avec des dizaines de tables qui ont toutes systématiquement conçu des clés de substitution, puis quelques tables de recherche qui utilisent des codes tiers comme PK, cela introduit une incohérence. Ce n'est pas tout à fait mauvais, mais cela nécessite une attention supplémentaire dans la documentation et ce qui peut ne pas être garanti. Ce sont des tables de recherche pour l'amour de Dieu, il est tout à fait correct d'utiliser une clé de substitution pour la cohérence.

Mise à jour basée sur des recherches supplémentaires:

Ok, la curiosité m'a mordu et j'ai décidé de faire des recherches sur les codes d'aéroport IATA pour le plaisir, en commençant par les liens fournis dans la question.

Il s'avère que les codes IATA ne sont pas aussi universels et faisant autorité que la question le fait croire. Selon cette page :

La plupart des pays utilisent des codes OACI à quatre caractères , et non des codes IATA, dans leurs publications aéronautiques officielles.

De plus, les codes IATA et les codes OACI sont distincts des codes d'identification FAA , qui sont encore une autre façon d'identifier les aérodromes.

Mon objectif n'est pas de lancer un débat sur les codes qui sont meilleurs ou plus universels ou plus autoritaires ou plus complets, mais de montrer exactement pourquoi concevoir votre structure de base de données autour d'un identifiant tiers arbitraire n'est pas quelque chose que je choisirais de faire. , à moins qu'il n'y ait une raison commerciale spécifique de le faire .

Dans ce cas, je pense que ma base de données serait mieux structurée, plus stable et plus flexible, en renonçant aux codes IATA (ou à tout code tiers, potentiellement modifiable) en tant que candidat de clé primaire et en utilisant une clé de substitution. Ce faisant, je peux renoncer à tous les pièges potentiels qui pourraient survenir en raison de la sélection de la clé primaire.

Eric King
la source
1
Les normes IATA sont donc assez bonnes pour les compagnies aériennes mais pas pour vous?
Tulains Córdova
1
Bien sûr, vous devrez vous joindre à la table de l'aéroport lorsque vous souhaitez rechercher des bagages à partir de Londres Heathrow, car vous ne pouvez pas le faire select * from baggage where airport_code = 'LHR', ce qui signifie que la base de données est uniquement utilisable via l'application, qui est très étroite et exclusive. approche, surtout lorsque le propriétaire de l'entreprise est celui qui a payé la base de données et qui en est le propriétaire. Vous devrez également écrire du code pour faire des choses banales comme importer des données d'une base de données à une autre pour éviter les colisions PK.
Tulains Córdova
1
Les codes IATA ne sont pas immuables et ne peuvent donc pas être considérés comme candidats PK. Exemple: le code IDL était à New York, jusqu'à ce qu'il soit renommé JFK. Le code IDL est maintenant au Mississippi.
James Snell
2
@EricKing IATA et ISO se soucient que les codes soient suffisamment stables, uniques et universellement acceptés. Cela coïncide beaucoup avec l'intérêt d'une personne qui conçoit une table.
Tulains Córdova, le
2
@ user61852 - ce n'est pas parce que ce sont des codes standard que le système de la compagnie aérienne les utilise comme PK (peut-être avez-vous plus d'informations ici?). Avoir une mise à jour en cascade à une échelle aussi massive semble être une très mauvaise idée.
JeffO
1

Tout en ayant des clés de substitution dans les champs est très bien et il n'y a rien de mal à ce que quelque chose à considérer pourrait être la taille de la page d'index elle-même.

Comme il s'agit d'une base de données relationnelle, vous ferez beaucoup de jointures et le fait d'avoir une clé de substitution de type numérique pourrait faciliter la gestion de la base de données, c'est-à-dire que la taille de la page d'index sera plus petite et donc plus rapide à rechercher. S'il s'agit d'un petit projet, cela n'aura pas d'importance et vous vous en sortirez sans aucun problème, mais plus l'application est grande, plus vous voudrez réduire les goulots d'étranglement.

Avoir un BIGINT, INT, SMALLINT, TINYINT ou tout autre type de données de type entier peut vous éviter des ennuis sur la route.

Juste mes 2 cents

MISE À JOUR:

Petit projet - utilisé par quelques-uns, peut-être même quelques dizaines de personnes. Petite échelle, projet de démonstration, projet pour usage personnel, quelque chose à ajouter à un portefeuille lors de la présentation de vos compétences sans expérience, etc.

Grand projet - utilisé par des milliers, des dizaines de milliers, des millions d'utilisateurs quotidiennement. Quelque chose que vous construirez pour une entreprise nationale / internationale avec une énorme base d'utilisateurs.

Habituellement, ce qui se passe est que quelques-uns des enregistrements sont souvent sélectionnés, et le serveur met en cache les résultats pour un accès rapide, mais de temps en temps, vous devez accéder à des enregistrements moins utilisés, auquel cas le serveur devrait plonger dans l'index page. (dans l'exemple ci-dessus avec les noms des aéroports, les gens voyagent souvent avec des compagnies aériennes nationales, par exemple Chichago -> Los Angeles, mais à quelle fréquence les gens volent-ils de Boston -> Zimbabwe)

Si VARCHAR est utilisé, cela signifie que l'espacement n'est pas uniforme, sauf si les données sont toujours de la même longueur (auquel point une valeur CHAR est plus efficace). Cela rend la recherche de l'index plus lente, et avec le serveur déjà occupé à gérer des milliers et des milliers de requêtes par seconde, il doit perdre du temps à parcourir un index non uniforme, et refaire la même chose sur les jointures (ce qui est plus lent que sélections régulières sur une table non optimisée, prenez l'exemple de DW où il y a aussi peu de jointures que possible pour accélérer la récupération des données). De plus, si vous utilisez UTF, cela peut également perturber le moteur de base de données (j'ai vu des cas).

Personnellement, d'après ma propre expérience, un index correctement organisé peut augmenter la vitesse d'une jointure d'environ 70%, et faire une jointure sur une colonne entière peut accélérer la jointure d'environ 25% (selon les données) . Au fur et à mesure que les tables principales commencent à croître et que ces tables sont utilisées, préférez-vous qu'un type de données entier occupe la colonne de quelques octets par rapport à un champ VARCHAR / CHAR qui occupera plus d'espace. Cela revient à économiser de l'espace disque, à augmenter les performances et la structure globale d'une base de données relationnelle.

En outre, comme James Snell l'a mentionné:

Les clés primaires doivent également être immuables, contrairement aux codes d'aéroport IATA. Ils peuvent être modifiés au gré de l'IATA.

Donc, en tenant compte de cela, préférez-vous mettre à jour 1 enregistrement lié à un nombre, plutôt que d'avoir à mettre à jour cet enregistrement plus tous les enregistrements de la table sur laquelle vous vous joignez.

Toni Kostelac
la source
C'est une pensée valable, mais l'intérêt de ces tableaux est qu'il n'y a qu'une quantité finie d'enregistrements dans chaque tableau. Si vous vouliez réellement dire la taille du code par small projectet bigger, veuillez mettre à jour pour clarifier pourquoi cela est important.
Bobson
1
Les restrictions concernant les PK immuables et les entiers numériques ne font pas partie du modèle relationnel (Codd) ou de toute norme SQL (ANSI ou autre).
Tulains Córdova
4
Les index basés sur une longueur fixe, des chaînes courtes (comme les codes ISO) sont aussi rapides que des entiers. Les index basés sur une longueur variable, les chaînes longues ne le sont pas.
Tulains Córdova
C'est ce que j'ai déclaré (voir la partie VARCHAR vs CHAR ci-dessus) je n'ai pas eu la chance de tester une chaîne courte de longueur fixe vs un entier numérique mais j'ai eu la chance de le faire avec une longueur variable et un entier
Toni Kostelac
2
Rejoindre la performance est un homme de paille. Souvent, l'utilisation de clés naturelles signifie que vous n'avez pas besoin d'une jointure en premier lieu.
Mike Sherrill 'Cat Recall'
1

Si vous adoptez l'approche "J'utilise des clés de substitution tout le temps", vous pouvez contourner ce type de problème. Ce n'est peut-être pas une bonne chose car il est important de réfléchir à vos données, mais cela économise certainement beaucoup de temps, d'énergie et d'efforts. Si quelqu'un devait adopter une acceptation de cette règle, les exemples énumérés sont certainement admissibles, car il faut un «acte de congrès» presque pour effectuer le changement.

Les requêtes ad hoc d'une base de données avec ces clés naturelles sont certainement utiles. La création de vues qui font la même chose en incluant les tables de recherche peut tout aussi bien fonctionner. Les bases de données modernes font un bien meilleur travail avec ce type de choses au point où cela n'a probablement pas d'importance.

Il existe des cas spécifiques aux États-Unis, où les normes ont été radicalement modifiées: le code postal est passé de 5 à 9 chiffres, les abréviations des États à 2 lettres cohérentes et se débarrassent de la période (rappelez-vous quand l'Illinois était malade?), Et la plupart des le monde a dû faire face à l'an 2000. Si vous avez une application en temps réel avec des données réparties dans le monde entier contenant des milliards d'enregistrements, les mises à jour en cascade ne sont pas la meilleure idée, mais ne devrions-nous pas tous travailler dans des endroits confrontés à de tels défis? Avec cet ensemble de données, vous pouvez le tester par vous-même et trouver une réponse plus diffinitive.

JeffO
la source
+1 Excellente réponse. La plupart du temps, les gens sont très dogmatiques sur cette question. De nombreux concepteurs de bases de données ont un ego géant et se considèrent comme les propriétaires de la base de données et des données. D'autres voient bien que le propriétaire des données ne peut les utiliser que via une application spécifique, car il ne peut pas les comprendre. Ils préfèrent également prendre des dispositions pour quelque chose qui pourrait ou non se produire à l'avenir tout en faisant un enfer de choses qui se font au quotidien, comme l'importation de données et l'écriture de requêtes. Échouer également à produire tout type de bibliographie canonique qui prend en charge leur point de vue.
Tulains Córdova
Soit dit en passant, la règle «J'utilise des clés de substitution tout le temps» n'est pas dans le modèle relationnel (Codd) ni dans aucun standard SQL. Le schéma du dictionnaire de données Oracle utilise autant que possible des clés naturelles et des clés artificielles dans les autres cas. PPDM ( ppdm.org ) recommande également l'approche mixte et l'utilise dans son modèle. ANSI SQL Standard ne dit rien sur tous les substituts. Je pense que tous les substituts et tout naturel sont corrosifs. Un modèle naturel et un substitut est ce que le modèle relationnel enseigne.
Tulains Córdova