Salut les agrumes,
Je m’amuse en ce moment à me développer mon propre lecteur RSS, et ce faisant j’arrive face à une problématique sur laquelle j’aimerais avoir votre avis.
J’ai mes données en base de données (du PostgreSQL pour être exact), et mon instance principale est destinée à être hébergée sur une machine assez mal pourvue en terme d’I/O disque. C’est un lecteur RSS multi-utilisateurs : chaque utilisateur voit seulement les flux qu’il a choisi de voir, et l’état de lecture n’influe pas sur les autres utilisateurs (je peux marquer un élément comme lu sans qu’il le soit pour mes amis).
J’ai donc besoin de savoir, pour chaque entrée de flux, si l’utilisateur présentement connecté a déjà lu ou non cette entrée de flux. De la même manière, chaque entrée de flux peut être mise en signet pour être facilement retrouvée (signets à plat, sans dossier). Le but c’est d’arriver à faire en sorte que ça fonctionne sans que le système explose en vol dès que je vais essayer de monter en puissance. Les volumétries sont : des centaines de milliers d’entrées de flux à terme ; idéalement des dizaines d’utilisateurs sans trop se poser de question existentielle. Statistiquement, pour N utilisateurs dans le système et E entrées, on devrait avoir environ (E/N) entrées lues par utilisateur – je pars du principe que les ensembles de flux de chaque utilisateur se recoupent assez mal, et qu’il y a peu de flux qui seront lus par tout le monde. Je suppose aussi que les utilisateurs sont actifs et lisent presque tous les éléments auxquels ils sont abonnés. Enfin, il n’y a pas de ménage des vieilles entrées.
Je vois trois solutions :
- Une table
read_entry
(et une autrebookmarked_entry
qui contiennent uniquement la paire(entry_id, member_id)
. L’entrée est considérée comme lue (respectivement en signet) pour l’utilisateur s’il y a une entrée dans cette table. C’est optimal en terme de stockage, mais de ce que j’ai compris de PostgreSQL, inefficace en terme de requêtes, parce que ça implique à faire desleft outer join
sur ces tables en recherchant les résultatsnull
, ce que le moteur SQL ne saurait pas optimiser. - Une table
member_entry
avecentry_id
,member_id
et deux booléensread
etbookmarked
. Toutes les paires (membre, entrée de flux) y sont sauvegardées et il suffit de filtrer sur l’un ou l’autre des booléens pour faire la requête, ce qui peut s’indexer très facilement. Par contre, cette table est par définition un produit cartésien et peut atteindre rapidement une taille considérable (je pars du principe qu’on a pas à gérer les cas où elle est mal remplie). - Et une solution non applicable qui consiste à dupliquer chaque entrée pour chaque utilisateur (si N personne sont abonnées au flux, chaque entrée du flux est présente N fois). En particulier parce que je stocke le contenu complet des entrées, ce qui peut vite faire exploser le truc avec des flux qui contiennent les articles entiers.
Pour l’instant je n’ai aucun vrai problème de performances (un utilisateur, 50 000 entrées), mais quand même je serais curieux de savoir ce que vous vous choisirez (ça peut être une solution 4 à laquelle je n’ai pas pensé) pour être paré dans le futur, surtout si je choisis d’ouvrir l’instance à pas mal d’autres de personnes (par exemple, des membres de ZdS).