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.
country_code est le code de pays standard ISO 3166-1 A3 , vous pouvez les voir aux Jeux olympiques.
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.
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?
la source
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:
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 :
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.
la source
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.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é:
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.
la source
small project
etbigger
, veuillez mettre à jour pour clarifier pourquoi cela est important.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.
la source