Quels sont les compromis pour incrémenter les identifiants par rapport aux clés de texte intégral pour les conceptions de clés étrangères?

8

Dans de nombreuses conceptions de bases de données relationnelles, certains champs sont référencés dans d'autres tables.

Par exemple, considérons une table utilisateur avec un nom d'utilisateur unique et une deuxième table stockant les données d'adresse.

Une disposition possible, que je dirais est l'approche courante, car j'ai observé dans la plupart des logiciels, est d'utiliser des identifiants d'incrémentation automatique comme ceci:

Table users
===========
userId int primary auto_increment
userName varchar unique

Table adressdata
==========
userId int references users.userId
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userId,adress_type))

C'est ainsi que je le faisais et comment je l'ai vu dans la plupart des cas.

Une autre façon serait:

Table users
===========
userName varchar primary

Table adressdata
==========
userName varchar references users.userName
adress_type varchar // for example country
address_value varchar // for example US
(you probably also want to put a unique key on (userName,adress_type))

Ici, nous stockons le nom d'utilisateur complet également dans la table des données d'adresse.

Pour moi, cela présente les avantages suivants:

  • Vous pouvez sélectionner le nom d'utilisateur immédiatement dans la table sans avoir à le joindre à une autre table. Dans cet exemple, c'est du point de vue de l'application probablement pas si pertinent, mais ce n'est qu'un exemple.

  • Il peut être plus facile de faire évoluer la base de données dans un environnement de réplication maître-maître, car il n'y a pas de conflits auto_increment.

Mais aussi les inconvénients:

  • L'espace requis pour l'index et les données (mais le plus pertinent sera probablement l'index) sur le champ dans la deuxième table est plus élevé.
  • Un changement de nom d'utilisateur devrait se propager à toutes les tables, ce qui consomme plus de ressources que de simplement le changer dans une table et laisser les ID tels quels.

À mon avis, il est beaucoup plus facile de travailler avec des champs de texte et de ne pas utiliser d'identifiants d'incrémentation, et les compromis sont minimes et dans la plupart des applications non pertinents.

Bien sûr, certains objets SONT identifiés avec un nombre incrémentiel par leur nature (par exemple, les messages du forum devraient recevoir un identifiant incrémentiel car il n'y a probablement pas d'autre champ unique comme le titre ou ainsi).

Mais avant de commencer à concevoir mes dispositions de base de données d'une manière complètement différente, je voudrais savoir s'il y a des choses auxquelles je n'ai pas pensé.

  • Existe-t-il des meilleures pratiques?

  • Y a-t-il des avantages / inconvénients auxquels je ne pensais pas et dont les effets pourraient survenir ultérieurement?

  • Comment concevez-vous personnellement des bases de données concernant les points ci-dessus et pourquoi?

Joe Hopfgartner
la source

Réponses:

3

Je suggère d'utiliser l'ID et non le nom d'utilisateur, car si vous commencez à utiliser le nom d'utilisateur comme colonne de jointure dans plusieurs tables, vous devez vous rappeler de les mettre à jour tous.

La clé étrangère de la userstable devient la clé primaire de la addressdatatable et la clé primaire doit rester stable. Il est recommandé de ne pas modifier les champs de clé primaire. Une clé primaire doit exister lors de la création de l'enregistrement et doit rester inchangée pendant toute la durée de vie de l'enregistrement.

Si vous souhaitez de plus amples informations Le grand débat sur la clé primaire est un excellent article.

stivlo
la source
2

Je suis fortement dans le camp "n'utilisez pas de clés naturelles". C'est parce que j'ai vu à quel point il est difficile sur le système lorsqu'ils sont mis à jour et pratiquement toutes les clés naturelles qui impliquent des noms de n'importe quel type sont mises à jour.

Les bases de données sont optimisées pour utiliser les jointures. Oui, vous pouvez enregistrer certaines jointures en utilisant des clés naturelles, mais les performances sont atteintes lorsque vous devez mettre à jour 1 000 000 d'enregistrements car un groupe de clés naturelles modifiées (ou même en fonction de ce qui se passe) peut être un énorme blocage.

Je n'utiliserais des clés naturelles que dans deux conditions:

  1. si la clé est assez garantie de ne pas changer (pensez aux numéros VIN automobiles) et
  2. s'il ne sera jamais réutilisé (même des éléments uniques comme les numéros de téléphone et les e-mails ne sont pas candidats à un PK car ils sont réutilisés lorsque quelqu'un cesse de les utiliser).

Et bien sûr, trop de clés naturelles censées être uniques ne le sont pas. Si vous êtes préoccupé par la réplication, vous pouvez utiliser des GUID.

HLGEM
la source
1

L'article de Wikipédia sur la clé de substitution contient quelques éléments intéressants dispersés:

  • "Les attributs qui identifient de manière unique une entité peuvent changer, ce qui peut invalider la pertinence des clés composées naturelles. " Par exemple, des restrictions ultérieures sur les noms d'utilisateur peuvent invalider les clés existantes lors de l'utilisation de la clé naturelle user namealors que cela n'affectera pas une clé synthétique.
  • " Les clés de substitution ne changent pas tant que la ligne existe. " Ainsi, vous n'avez pas besoin (manuellement ou automatiquement) de modifier en cascade les modifications de clés dans les tables de références.
  • " Les valeurs des clés de substitution générées n'ont aucun rapport avec la signification réelle des données contenues dans une rangée. " Cela peut rendre l'audit difficile.

Je crois que le lecteur attentif peut trouver des points supplémentaires à considérer.


la source
Bonne réponse. De nombreuses clés naturelles ont tendance à changer. Cela les rend impropres aux clés qui peuvent être référencées comme clés étrangères. Il existe de nombreuses raisons pour lesquelles il est approprié de modifier l'ID utilisateur d'un utilisateur.
BillThor
1

Je posterai de mon expérience qui sera probablement très différente de ce que les différents DBA pourraient suggérer. Je suis principalement orienté vers un mélange de performances et de maintenabilité lors de la conception de bases de données pour divers projets.

Je n'utiliserais jamais, jamais une clé naturelle pour la clé primaire. Surtout si j'utilise MySQL / InnoDB. Je n'ai toujours vu aucun avantage à utiliser une clé naturelle, généralement ce que je vois sont des implications de performance si rien. J'ai mis en gras «jamais, jamais» uniquement parce que les clés naturelles servaient à créer des porcs de performance pour mes projets. La substitution (entier) a toujours été un meilleur choix. Certains pourraient ne pas être d'accord, mais nous vivons dans un monde où la performance joue un rôle sur la théorie.

En ce qui concerne les JOIN, je n'essaie pas de les éviter à tout prix mais j'ai tendance à les optimiser. J'essaie d'abuser autant que possible de l'index cluster d'InnoDB (clé primaire). Si les JOIN sont effectués via des PK, ils sont extrêmement rapides. J'ai également tendance à éviter les FK où ils n'ont aucun sens. Honnêtement, je ne me soucierais pas tellement de l'intégrité des données lorsqu'il s'agit de lier les utilisateurs et leurs informations d'adresse. Je l'appliquerais lors de la liaison des factures aux articles aux utilisateurs. L'utilisation excessive des FK est une exagération et un cauchemar à maintenir après avoir référencé tout, pensant que c'est un excellent design pour maintenir des relations partout. À un moment donné, les choses doivent changer et lorsque MySQL commence à se plaindre de l'erreur 150 en permanence, vous voulez juste rentrer à la maison.

Vous avez également mentionné la réplication et éviter les conflits en raison de la nature des incréments automatiques. J'avais un projet où nous avions une quantité de bases de données stockant des informations sur les ventes de produits, la quantité de bases de données était variable. Chaque jour, les bases de données étaient répliquées dans une base de données "principale" que nous utilisions pour exécuter les rapports. J'ai évité les conflits PK en créant une clé primaire composée à partir d'une partie auto_increment et d'une autre partie INT qui indiquait l'emplacement d'où provenait l'enregistrement. De cette façon, je pouvais suivre d'où venaient les choses et je n'ai rien perdu (les produits avaient le même ID, seul l'identifiant de l'emplacement a été changé).

NB
la source