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?
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é).
la source