Nous y revoilà, le vieil argument se pose encore ...
Faudrait-il mieux avoir une clé métier en tant que clé primaire ou préférerions-nous avoir un identifiant de substitution (c'est-à-dire une identité SQL Server) avec une contrainte unique sur le champ de clé métier?
Veuillez fournir des exemples ou des preuves pour étayer votre théorie.
Tous les deux. Avoir votre gâteau et le manger.
N'oubliez pas qu'une clé primaire n'a rien de spécial, sauf qu'elle est étiquetée comme telle. Ce n'est rien de plus qu'une contrainte NOT NULL UNIQUE, et une table peut en avoir plusieurs.
Si vous utilisez une clé de substitution, vous souhaitez toujours une clé métier pour garantir l'unicité des règles métier.
Quelques raisons d'utiliser des clés de substitution:
Stabilité: Changer une clé en raison d'un besoin commercial ou naturel aura un impact négatif sur les tables associées. Les clés de substitution doivent rarement, sinon jamais, être modifiées car aucune signification n'est liée à la valeur.
Convention: Vous permet d'avoir une convention d'appellation des colonnes de clé primaire normalisée plutôt que de devoir réfléchir à la façon de joindre des tables avec différents noms pour leurs clés de performance.
Vitesse: En fonction de la valeur et du type de PK, une clé de substitution d'un entier peut être plus petite, plus rapide à indexer et à rechercher.
Il semble que personne n’ait encore dit quoi que ce soit à l’appui des clés non substitutives (j’hésite à dire "naturelles"). Alors voilà ...
Un inconvénient des clés de substitution est qu’elles ne sont pas de sens (cité comme avantage par certains, mais ...). Cela vous oblige parfois à joindre beaucoup plus de tables à votre requête que nécessaire. Comparer:
select sum(t.hours)
from timesheets t
where t.dept_code = 'HR'
and t.status = 'VALID'
and t.project_code = 'MYPROJECT'
and t.task = 'BUILD';
contre:
select sum(t.hours)
from timesheets t
join departents d on d.dept_id = t.dept_id
join timesheet_statuses s on s.status_id = t.status_id
join projects p on p.project_id = t.project_id
join tasks k on k.task_id = t.task_id
where d.dept_code = 'HR'
and s.status = 'VALID'
and p.project_code = 'MYPROJECT'
and k.task_code = 'BUILD';
À moins que quelqu'un pense sérieusement que ce qui suit est une bonne idée ?:
select sum(t.hours)
from timesheets t
where t.dept_id = 34394
and t.status_id = 89
and t.project_id = 1253
and t.task_id = 77;
"Mais", dira quelqu'un, "que se passera-t-il lorsque le code de MYPROJECT, VALID ou HR changera?" A quoi ma réponse serait: "pourquoi auriez-vous besoin de pour le changer?" Ce ne sont pas des clés "naturelles" dans le sens où un organisme extérieur va légiférer pour que "VALID" soit dorénavant codé "BON". Seul un faible pourcentage de clés "naturelles" entrent vraiment dans cette catégorie - SSN et Code postal étant les exemples habituels. J'utiliserais certainement une clé numérique sans signification pour des tables telles que Person, Address - mais pas pour tout , ce que, pour une raison quelconque, la plupart des gens ici semblent préconiser.
Voir aussi: ma réponse à une autre question
La clé de substitution n'aura JAMAIS de raison de changer. Je ne peux pas en dire autant des clés naturelles. Noms de famille, courriels, numéros ISBN - ils peuvent tous changer un jour.
Les clés de substitution (généralement des entiers) ont pour valeur ajoutée de rendre vos relations de table plus rapides, plus économiques en termes de stockage et de rapidité de mise à jour (encore mieux, les clés étrangères n'ont pas besoin d'être mises à jour lors de l'utilisation de clés de substitution, contrairement aux champs de clé métier, cela change de temps en temps).
La clé primaire d'une table doit être utilisée pour identifier de manière unique la ligne, principalement à des fins de jointure. Table Think a Persons: les noms peuvent changer et ils ne sont pas garantis uniques.
Pensez aux entreprises: vous êtes une entreprise Merkin heureuse qui fait des affaires avec d’autres entreprises à Merkia. Vous êtes assez intelligent pour ne pas utiliser le nom de la société comme clé primaire. Vous utilisez donc l'identifiant de société unique du gouvernement Merkia dans son intégralité de 10 caractères alphanumériques. Ensuite, Merkia modifie les identifiants de société car ils pensaient que ce serait une bonne idée. Ce n'est pas grave, vous utilisez la fonctionnalité de mises à jour en cascade de votre moteur de base de données, pour un changement qui ne devrait pas vous concerner en premier lieu. Plus tard, votre entreprise se développe et vous travaillez maintenant avec une entreprise à Freedonia. Les identifiants de société Freedonian peuvent comporter jusqu'à 16 caractères. Vous devez agrandir la clé primaire de l'ID de la société (ainsi que les champs de la clé étrangère dans les commandes, les problèmes, les transferts d'argent, etc.), en ajoutant un champ Pays dans la clé primaire (ainsi que dans les clés étrangères). Aie! Guerre civile en Freedonia, elle est divisée en trois pays. Le nom de pays de votre associé doit être changé pour le nouveau; mises à jour en cascade à la rescousse. BTW, quelle est votre clé primaire? (Pays, Identifiant de la société) ou (Identifiant de la société, Pays)? Ce dernier aide les jointures, le premier évite un autre index (ou peut-être plusieurs, si vous souhaitez également que vos commandes soient regroupées par pays).
Tous ces éléments ne constituent pas une preuve, mais une indication qu'une clé de substitution identifiant de manière unique une ligne pour toutes les utilisations, y compris les opérations de jointure, est préférable à une clé métier.
Je déteste les clés de substitution en général. Ils ne doivent être utilisés qu'en l'absence de clé naturelle de qualité. C'est assez absurde quand on y pense, de penser que l'ajout de données sans signification à votre table pourrait améliorer les choses.
Voici mes raisons:
Lors de l'utilisation de clés naturelles, les tables sont regroupées de la manière dont elles sont le plus souvent recherchées, ce qui accélère les requêtes.
Lorsque vous utilisez des clés de substitution, vous devez ajouter des index uniques sur les colonnes de clés logiques. Vous devez toujours empêcher les données en double logique. Par exemple, vous ne pouvez pas autoriser deux organisations portant le même nom dans votre table d’organisation, même si le pk est une colonne d’identificateur de substitution.
Lorsque des clés de substitution sont utilisées comme clé primaire, il est beaucoup moins clair de savoir quelles sont les clés primaires naturelles. Lors du développement, vous voulez savoir quel jeu de colonnes rend la table unique.
Dans une à plusieurs chaînes de relations, les chaînes de clés logiques. Ainsi, par exemple, les organisations ont de nombreux comptes et les comptes ont de nombreuses factures. La clé logique de l'organisation est donc OrgName. La clé logique des comptes est OrgName, AccountID. La clé logique de la facture est OrgName, AccountID, InvoiceNumber.
Lorsque des clés de substitution sont utilisées, les chaînes de clés sont tronquées car une clé étrangère est attribuée au parent immédiat. Par exemple, la table Facture n'a pas de colonne OrgName. Il a seulement une colonne pour le AccountID. Si vous souhaitez rechercher des factures pour une organisation donnée, vous devez joindre les tables Organisation, Compte et Facture. Si vous utilisez des clés logiques, vous pouvez alors interroger directement la table d'organisation.
Le stockage des valeurs de clé de substitution des tables de recherche a pour effet de remplir les tables avec des entiers sans signification. Pour afficher les données, vous devez créer des vues complexes qui se joignent à toutes les tables de recherche. Une table de correspondance est destinée à contenir un ensemble de valeurs acceptables pour une colonne. Il ne devrait pas être codifié en stockant une clé de substitution entière. Rien dans les règles de normalisation ne vous suggère de stocker un entier de substitution à la place de la valeur elle-même.
J'ai trois livres de base de données différents. Aucun d'entre eux ne montre à l'aide de clés de substitution.
Je souhaite partager mon expérience avec vous sur cette guerre sans fin: D sur un dilemme naturel vs clé de substitution. Je pense que les deux clés de substitution (clés artificielles auto-générées) et les clés naturelles (composées de colonnes avec une signification de domaine) ont avantages et inconvénients . Donc, selon votre situation, il pourrait être plus pertinent de choisir l'une ou l'autre méthode.
Comme il semble que de nombreuses personnes présentent les clés de substitution comme la solution presque parfaite et les clés naturelles comme la peste, je me concentrerai sur les arguments de l'autre point de vue:
Les clés de substitution sont:
Utilisez les clés naturelles lorsque cela est pertinent et utilisez les clés de substitution lorsqu'il est préférable de les utiliser.
J'espère que cela a aidé quelqu'un!
Utilisez toujours une clé qui n’a aucune signification professionnelle. C'est juste une bonne pratique.
EDIT: J'essayais de trouver un lien en ligne, mais je ne pouvais pas. Cependant, dans 'Patterns of Enterprise Archtecture' [Fowler], vous avez une bonne explication de la raison pour laquelle vous ne devriez pas utiliser autre chose qu'une clé sans signification autre que celle d'être une clé. Cela se résume au fait qu’il ne devrait y avoir qu’un seul travail.
Les clés de substitution sont très pratiques si vous envisagez d'utiliser un outil ORM pour gérer/générer vos classes de données. Bien que vous puissiez utiliser des clés composites avec certains des mappeurs les plus avancés (read: hibernate), cela ajoute une certaine complexité à votre code.
(Bien entendu, les puristes de la base de données diront que même la notion de clé de substitution est une abomination.)
Je suis fan de l'utilisation des uids pour les clés de substitution lorsque cela convient. La principale victoire avec eux est que vous connaissez la clé à l’avance, par exemple. vous pouvez créer une instance d'une classe dont l'ID est déjà défini et garanti d'être unique, tandis qu'avec une clé entière, par exemple, vous devez définir par défaut la valeur 0 ou -1 et mettre à jour une valeur appropriée lorsque vous enregistrez/mettez à jour.
Les UID comportent des pénalités en termes de recherche et de rapidité d'adhésion, de sorte que cela dépend de l'application en question pour déterminer si elles sont souhaitables.
À mon avis, il est préférable d’utiliser une clé de substitution car il n’ya aucune chance que cela change. Presque tout ce que je pourrais penser que vous pourriez utiliser comme clé naturelle pourrait changer (disclaimer: pas toujours vrai, mais généralement).
Un exemple pourrait être une BD de voitures - à première vue, vous pourriez penser que la plaque d'immatriculation pourrait être utilisée comme clé. Mais ceux-ci pourraient être modifiés pour que ce soit une mauvaise idée. Vous ne voudriez pas vraiment savoir cela après relâchant l'application, quand quelqu'un vient vous demander pourquoi il ne peut pas changer sa plaque d'immatriculation en une nouvelle et brillante carte personnalisée.
Toujours utiliser une seule colonne, clé de substitution si possible. Cela rend les jointures ainsi que les insertions/mises à jour/suppressions beaucoup plus propres car vous êtes uniquement responsable du suivi d'une seule information pour maintenir l'enregistrement.
Ensuite, si nécessaire, empilez vos clés d’entreprise sous forme de contraintes ou d’index uniques. Cela vous préservera l'intégrité des données.
La logique métier/les clés naturelles peuvent changer, mais la clé physique d'une table ne doit JAMAIS changer.
Dans un scénario de datawarehouse, je pense qu’il est préférable de suivre le chemin de la clé de substitution. Deux raisons:
C'est l'un de ces cas où une clé de substitution a à peu près toujours un sens . Dans certains cas, vous pouvez choisir ce qui convient le mieux à la base de données ou à votre modèle d’objet, mais dans les deux cas, utiliser une clé dénuée de sens ou GUID est une meilleure idée. Il facilite l’indexation et plus vite, et c’est une identité pour votre objet qui ne change pas.
Pour rappel, il est déconseillé de placer des index clusterisés sur des clés de substitution aléatoires, par exemple des GUID lisant XY8D7-DFD8S, car SQL Server n’est pas en mesure de trier ces données physiquement. Vous devez plutôt placer des index uniques sur ces données, bien qu'il soit également avantageux d'exécuter simplement le profileur SQL pour les opérations de la table principale, puis de placer ces données dans l'assistant de paramétrage du moteur de base de données.
Voir la discussion @ http://social.msdn.Microsoft.com/Forums/en-us/sqlgetstarted/thread/27bd9c77-ec31-44f1-ab7f-bd2cb13129be
Cas 1: Votre table est une table de consultation avec moins de 50 types (insertions)
Utilisez clés commerciales/naturelles. Par exemple:
Table: JOB with 50 inserts
CODE (primary key) NAME DESCRIPTION
PRG PROGRAMMER A programmer is writing code
MNG MANAGER A manager is doing whatever
CLN CLEANER A cleaner cleans
...............
joined with
Table: PEOPLE with 100000 inserts
foreign key JOBCODE in table PEOPLE
looks at
primary key CODE in table JOB
Cas 2: Votre table est un table avec des milliers d'insertions
Utilisez clés de substitution/auto-incrémentation. Par exemple:
Table: ASSIGNMENT with 1000000 inserts
joined with
Table: PEOPLE with 100000 inserts
foreign key PEOPLEID in table ASSIGNMENT
looks at
primary key ID in table PEOPLE (autoincrement)
Dans le premier cas:
Dans le second cas:
Les clés de substitution peuvent être utiles lorsque les informations commerciales peuvent changer ou être identiques. Les noms commerciaux ne doivent pas nécessairement être uniques à travers le pays, après tout. Supposons que vous traitiez avec deux entreprises nommées Smith Electronics, une au Kansas et une au Michigan. Vous pouvez les distinguer par adresse, mais cela changera. Même l'état peut changer; Et si Smith Electronics de Kansas City (Kansas) traversait la rivière pour se rendre à Kansas City (Missouri)? Il n'y a pas de moyen évident de garder ces entreprises distinctes avec des informations de clé naturelle, une clé de substitution est donc très utile.
Pensez à la clé de substitution comme un numéro ISBN. Habituellement, vous identifiez un livre par son titre et son auteur. Cependant, j'ai deux livres intitulés "Pearl Harbor" par H. P. Willmott, et ce sont définitivement des livres différents, pas seulement des éditions différentes. Dans un cas comme celui-là, je pourrais faire référence à l'apparence des livres, ou au plus tôt au plus récent, mais c'est tout aussi bien que je dispose de l'ISBN.
Cheval pour les cours. Énoncer mon parti pris; Je suis un développeur avant tout, je suis donc principalement préoccupé de donner aux utilisateurs une application fonctionnelle.
J'ai travaillé sur des systèmes avec des clés naturelles et j'ai dû passer beaucoup de temps à faire en sorte que les changements de valeur se répercutent.
J'ai travaillé sur des systèmes avec uniquement des clés de substitution et le seul inconvénient est le manque de données dénormalisées pour le partitionnement.
La plupart des développeurs PL/SQL traditionnels avec lesquels j'ai travaillé n'aimaient pas les clés de substitution, à cause du nombre de tables par jointure, mais nos bases de données de test et de production ne faisaient jamais de bruit. les jointures supplémentaires n'ont pas affecté les performances de l'application. Avec les dialectes de base de données qui ne prennent pas en charge des clauses telles que "X jointure interne Y sur Xa = Yb", ou les développeurs qui n'utilisent pas cette syntaxe, les jointures supplémentaires pour les clés de substitution rendent les requêtes plus difficiles à lire et plus longues à taper et vérifier: voir @Tony Andrews post. Mais si vous utilisez un ORM ou tout autre framework de génération SQL, vous ne le remarquerez pas. La dactylographie atténue également.
Peut-être pas tout à fait pertinent pour ce sujet, mais un mal de tête que j'ai avec les clés de substitution. L'analyse prédéfinie Oracle crée des SK générés automatiquement sur toutes ses tables de dimensions de l'entrepôt, et les stocke également dans les faits. Ainsi, chaque fois que les dimensions doivent être rechargées au fur et à mesure que de nouvelles colonnes sont ajoutées ou doivent être renseignées pour tous les éléments de la dimension, les SK affectés lors de la mise à jour les synchronisent avec les valeurs d'origine stockées dans le fait, forçant une recharge complète de toutes les tables de faits qui s'y joignent. Je préférerais que même si le SK était un nombre sans signification, il y aurait un moyen de ne pas changer pour les enregistrements originaux/anciens. Comme beaucoup le savent, les solutions prêtes à l'emploi répondent rarement aux besoins d'une organisation et nous devons constamment les personnaliser. Nous avons maintenant une valeur de données de 3 ans dans notre entrepôt et les rechargements complets à partir des systèmes Oracle Financial sont très importants. Donc, dans mon cas, elles ne sont pas générées à partir de la saisie de données, mais ajoutées dans un entrepôt pour aider à la création de rapports de performances. Je comprends, mais les nôtres changent et c'est un cauchemar.
Dans le cas d'une base de données ponctuelle, il est préférable de combiner des clés de substitution et des clés naturelles. par exemple. vous devez suivre les informations d'un membre pour un club. Certains attributs d'un membre ne changent jamais. Par exemple, la date de naissance mais le nom peut changer. Créez donc une table Member avec une clé de substitution member_id et une colonne pour la date de naissance. Créez une autre table appelée nom de personne et définissez des colonnes pour member_id, member_fname, member_lname, date_updated. Dans cette table, la clé naturelle serait member_id + date_updated.