Disons que j'ai une application de base de données relationnelle et un objet "utilisateur" et un objet "message". Maintenant, je veux montrer le nombre de messages non lus à cet utilisateur.
Quelle est la meilleure façon d'archiver cela? Dois-je introduire un champ dans l'utilisateur et le compter si l'utilisateur reçoit un message et diminuer le nombre s'il en lit un? Ou dois-je exécuter une requête à chaque fois pour calculer le nombre de messages pour l'utilisateur qui sont marqués comme non lus?
Je pense que la première approche est plus compliquée et sujette aux erreurs, mais fonctionnera mieux que la deuxième approche.
Comment cela se fait-il normalement ou quelle est la meilleure approche?
Réponses:
La meilleure approche consiste à l'essayer d'abord sans champ supplémentaire, à mesurer les performances, et si cela s'avère vraiment trop lent, vous essayez d'optimiser. Cela pourrait signifier passer à votre première approche en utilisant un champ supplémentaire, mais vous devriez également envisager de tester d'autres options, par exemple, en mettant un index supplémentaire sur les champs combinés ("non lus", "ID utilisateur") sur vos messages.
la source
La solution de manuel selon la théorie de la base de données serait de n'avoir aucune valeur dans votre base de données qui dépende des valeurs d'autres données, car ce sont des dépendances transitives . Avoir des champs qui sont des valeurs calculées basées sur d'autres champs est une violation de la normalisation, car cela conduit à des informations redondantes.
Cependant, parfois ce que dit le manuel et quelle est la méthode la plus pratique dans la pratique diffèrent. Compter le nombre de messages non lus chaque page vue pourrait être une opération assez coûteuse. La mise en cache du nombre dans la
user
table serait bien meilleure pour les performances. Le coût serait qu'il pourrait y avoir des incohérences dans la base de données: il pourrait être possible qu'un message soit supprimé, ajouté ou lu sans se rappeler de mettre également à jour le compteur non lu.la source
INSERT
ouDELETE
. (OuUPDATE
, pour tenir compte du changement de propriétaire d'un message.). Un bon SGBD fera l'opération et exécutera les déclencheurs dans la même transaction, donc tout ou rien se produira.Le problème potentiel est la performance et vous n'avez pas encore de problème de performance. Il y a beaucoup de choses que vous pouvez faire en fonction de la base de données de votre choix pour gérer cela dans la solution # 1: indexation, matériel, mise en cache, etc. Tout dépend de la fréquence à laquelle l'utilisateur a besoin pour obtenir un nombre de messages non lus en cours. Beaucoup de ces choix ne nécessitent pas de codage personnalisé du côté de l'application, vous pouvez donc les implémenter avec un changement de code ou très peu. Facilite la croissance avec l'application.
Une fois qu'un utilisateur se connecte / se connecte, obtenir le décompte de la base de données une fois n'est pas si mal. Votre application conservera-t-elle une liste de messages constamment mise à jour comme les e-mails? Obtenir un décompte non lu à partir d'ici ne nécessite pas un autre voyage dans la base de données et pour obtenir de nouveaux messages, il faudra quand même faire un voyage db.
Faire un voyage vers la base de données à chaque fois qu'un message est lu pour signaler IsRead? champ suffit sans recalculer un autre champ.
Avec la solution n ° 2 (garder un décompte dans un champ / sur disque), aurez-vous besoin d'une routine pour reconstruire / recalculer périodiquement ce champ en cas de problème? Et il y a toujours des problèmes. Allez-vous envelopper tout cela dans une transaction? Chaque fois que quelqu'un envoie un message à quelqu'un d'autre, il peut échouer car il ne peut pas mettre à jour le UnreadCount de l'utilisateur destinataire en raison d'un verrouillage de la table User? Ou allez-vous créer une table distincte pour ce champ?
la source
La façon dont je le ferais est d'exécuter une requête à chaque fois, c'est-à-dire votre deuxième approche. Assurez-vous simplement d'ajouter un index dans votre table de messages sur la colonne qui agit comme une clé étrangère dans la table des utilisateurs pour améliorer les performances de votre requête.
Ensuite, comme le dit Doc, mesurez les performances de cette approche et vous pourrez alors dire si vous devez prendre un chemin différent.
la source