Je suis un développeur de logiciels. J'adore coder, mais je déteste les bases de données ... Actuellement, je crée un site Web sur lequel un utilisateur sera autorisé à marquer une entité comme aimée (comme dans FB), à la taguer et à la commenter .
Je reste bloqué sur la conception des tables de base de données pour gérer cette fonctionnalité. La solution est triviale, si nous ne pouvons le faire que pour un seul type de chose (par exemple, des photos). Mais je dois l'activer pour 5 choses différentes (pour le moment, mais je suppose également que ce nombre peut augmenter à mesure que l'ensemble du service se développe).
J'ai trouvé des questions similaires ici, mais aucune d'entre elles n'a de réponse satisfaisante, alors je pose à nouveau cette question.
La question est de savoir comment concevoir correctement, efficacement et élastiquement la base de données, afin qu'elle puisse stocker des commentaires pour différentes tables , des likes pour différentes tables et des balises pour elles. Un modèle de conception comme réponse sera le meilleur;)
Description détaillée : J'ai un tableau User
avec quelques données utilisateur, et 3 autres tableaux : Photo
avec des photos , Articles
avec des articles , Places
avec des lieux . Je souhaite permettre à tout utilisateur connecté de:
commenter l'un de ces 3 tableaux
marquer l'un d'entre eux comme aimé
taguer l'un d'eux avec un tag
Je veux également compter le nombre de likes pour chaque élément et le nombre de fois que cette balise particulière a été utilisée.
1 er approche :
a) Pour les étiquettes , je vais créer un tableau Tag [TagId, tagName, tagCounter]
, je vais créer beaucoup à plusieurs relations tables pour: Photo_has_tags
, Place_has_tag
, Article_has_tag
.
b) La même chose vaut pour les commentaires.
c) Je vais créer un tableau LikedPhotos [idUser, idPhoto]
, LikedArticles[idUser, idArticle]
, LikedPlace [idUser, idPlace]
. Le nombre de likes sera calculé par des requêtes (ce qui, je suppose, est mauvais). Et...
Je n'aime vraiment pas ce design pour la dernière partie, ça sent mauvais pour moi;)
2 ème approche :
Je vais créer une table ElementType [idType, TypeName == some table name]
qui sera remplie par l'administrateur (moi) avec les noms des tables qui peuvent être aimées , commentées ou étiquetées . Ensuite, je créerai des tableaux :
a) LikedElement [idLike, idUser, idElementType, idLikedElement]
et la même chose pour les commentaires et les balises avec les colonnes appropriées pour chacun. Maintenant, quand je veux faire une photo aimée, je vais insérer:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
et pour les lieux:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
et ainsi de suite ... Je pense que la deuxième approche est meilleure, mais j'ai aussi l'impression que quelque chose manque également dans cette conception ...
Enfin, je me demande aussi quel est le meilleur endroit pour stocker le comptoir pour combien de fois l'élément a été aimé. Je ne peux penser qu'à deux façons:
- dans la
Photo/Article/Place
table element ( ) - en sélectionnant count ().
J'espère que mon explication de la question est maintenant plus approfondie.
Réponses:
La solution la plus extensible est de n'avoir qu'une seule table "de base" (connectée aux "likes", balises et commentaires), et en "hériter" toutes les autres tables. Ajouter un nouveau type d'entité implique simplement d'ajouter une nouvelle table "héritée" - elle se connecte alors automatiquement à l'ensemble de la machine like / tag / comment.
Le terme entité-relation pour cela est "catégorie" (voir le Guide des méthodes ERwin , section: "Relations de sous-types"). Le symbole de catégorie est:
En supposant qu'un utilisateur peut aimer plusieurs entités, une même balise peut être utilisée pour plus d'une entité mais un commentaire est spécifique à l'entité, votre modèle pourrait ressembler à ceci:
BTW, il existe environ 3 façons d'implémenter la "catégorie ER":
À moins que vous n'ayez des exigences de performances très strictes, la troisième approche est probablement la meilleure (ce qui signifie que les tables physiques correspondent 1: 1 aux entités du diagramme ci-dessus).
la source
BIGINT
est 9223372036854775807. En supposant que vous insérez une ligne chaque seconde, vous manquerez de valeurs disponibles dans environ 300 milliards d'années. Vous pourrez sûrement porter des entiers de 128 bits d'ici là!Puisque vous «détestez» les bases de données, pourquoi essayez-vous d'en implémenter une? Au lieu de cela, demandez l'aide de quelqu'un qui aime et respire ce genre de choses.
Sinon, apprenez à aimer votre base de données. Une base de données bien conçue simplifie la programmation, l'ingénierie du site et facilite son fonctionnement continu. Même un concepteur d / b expérimenté n'aura pas une vision complète et parfaite: certains changements de schéma seront nécessaires à mesure que les modèles d'utilisation émergent ou que les exigences changent.
S'il s'agit d'un projet individuel, programmez l'interface de la base de données dans des opérations simples à l'aide de procédures stockées: add_user, update_user, add_comment, add_like, upload_photo, list_comments, etc. N'incorporez pas le schéma dans une seule ligne de code. De cette manière, le schéma de la base de données peut être modifié sans affecter aucun code: seules les procédures stockées doivent connaître le schéma.
Vous devrez peut-être refactoriser le schéma plusieurs fois. C'est normal. Ne vous inquiétez pas de le rendre parfait du premier coup. Rendez-le simplement suffisamment fonctionnel pour prototyper une conception initiale. Si vous avez le luxe du temps, utilisez-le un peu, puis supprimez le schéma et recommencez. C'est toujours mieux la deuxième fois.
la source
Ceci est une idée générale, veuillez ne pas prêter beaucoup d'attention au style des noms de champs, mais plus à la relation et à la structure
Ce pseudocode obtiendra tous les commentaires de photo avec l'ID 5
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
Ce pseudocode obtiendra tous les goûts ou utilisateurs qui ont aimé la photo avec l'ID 5
(vous pouvez utiliser count () pour obtenir simplement le nombre de likes)
la source
SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
id_stuff
colonne contiendra-t-elle des valeurs uniques dans chacune des trois tables?pour autant que je sache. plusieurs tables sont nécessaires. Il existe une relation plusieurs à plusieurs entre eux.
la source
Regardez les modèles d'accès dont vous aurez besoin. L'un d'entre eux semble-t-il avoir rendu particulièrement difficile ou inefficace mon choix de conception ou l'autre?
Sinon privilégiez celui qui nécessite le moins de tables
Dans ce cas:
Je pense que votre approche «discriminée», option 2, donne des requêtes plus simples dans certains cas et ne semble pas beaucoup plus mauvaise dans les autres, alors je l'accepterais.
la source
Allez certainement avec la deuxième approche où vous avez une table et stockez le type d'élément pour chaque ligne, cela vous donnera beaucoup plus de flexibilité. Fondamentalement, quand quelque chose peut logiquement être fait avec moins de tables, il est presque toujours préférable d'utiliser moins de tables. Un avantage qui me vient à l'esprit en ce moment à propos de votre cas particulier, considérez que vous souhaitez supprimer tous les éléments appréciés d'un certain utilisateur, avec votre première approche, vous devez émettre une requête pour chaque type d'élément, mais avec la deuxième approche, cela peut être fait avec une seule requête ou considérez quand vous voulez ajouter un nouveau type d'élément, avec la première approche, cela implique de créer une nouvelle table pour chaque nouveau type mais avec la deuxième approche, vous ne devriez rien faire ...
la source
Pensez à utiliser une table par entité pour les commentaires, etc. Plus de tables - meilleur partitionnement et mise à l'échelle. Ce n'est pas un problème de contrôler de nombreuses tables similaires pour tous les frameworks que je connais.
Un jour, vous devrez optimiser les lectures à partir d'une telle structure. Vous pouvez facilement créer des tables agragantes par rapport à celles de base et perdre un peu en écriture.
Une grande table avec dictionnaire peut devenir un jour incontrôlable.
la source