Question

J'essaie de trouver une solution optimale au problème suivant: il est nécessaire de concevoir une base de données (basée sur Postgres), son système de déclencheurs et de compteurs, qui formera un système d'interrogation, de mise à jour et de stocker des informations sur "la quantité de commentaires non lus dans chaque article (ou entrée de blog, ou similaire) affichée sur la page".

Chaque solution qui vient à l’esprit présente de sérieux inconvénients, que ce soit au niveau de la requête, du stockage ou de la mise à jour. C'est à dire. il a besoin de trop de stockage, de mises à jour ou de requêtes trop coûteuses.

Qu'en est-il de votre expérience? Peut-être existe-t-il une solution intéressante déjà formée pour ce genre de problèmes?

Était-ce utile?

La solution

Je voudrais garder le schéma aussi simple que possible, donc les requêtes seront aussi simples que possible. Cela a généralement aussi les exigences de stockage les plus faibles. Bien sûr, définissez des index pour prendre en charge cette requête.

Étape suivante: mesurez les performances! "Mesurer, c'est savoir." Quel est le temps de réponse? Quelle est la charge sur le serveur? Tant que les performances sont acceptables, gardez le schéma et la requête simples. Ne sacrifiez pas la maintenabilité si cela n’est pas absolument nécessaire: vos successeurs vous en remercieront plus tard.

Si les performances sont réellement un problème, examinez la fonctionnalité de mise en cache du framework que vous utilisez pour votre application. NE PAS effectuer une requête est toujours plus rapide que d’en effectuer une optimisée.

Autres conseils

Si vous ne réussissez vraiment pas dans votre enveloppe de ressources, vous devez peut-être modifier l'expérience utilisateur. Stocker la date du dernier accès à un fil suffit peut-être.

Je ne crois pas que l'approche standard normalisée vous laisserait avec des requêtes inefficaces. Supposons que vous ayez une table commentaires_article avec PK (article_id, ID_de commentaire) et une autre table comments_seen_by_user avec PK (utilisateur_id, article_id, commentaire_id) . Tout ce que vous devez faire est, pour chaque article figurant sur la page:

SELECT count(*) FROM article_comments ac
WHERE article_id = ?                -- Parameter
AND NOT EXISTS (
    SELECT 1 FROM comments_seen_by_user csbu
    WHERE csbu.user_id = ?          -- Parameter
    AND   csbu.article_id = ac.article_id
    AND   csbu.comment_id = ac.comment_id
)

Si vous affichez 20 articles sur une page, vous exécuterez la requête ci-dessus 20 fois. Chaque exécution utilisera un index pour extraire 10 à 20 lignes de article_comments , ainsi que la sous-requête. test est juste un autre balayage d'index sur comments_seen_by_user , donc au total, vous pourriez avoir 20 * (20 * 2) = 800 recherches indexées à effectuer pour afficher une page donnée. Ce n'est pas une sueur pour un DB moderne. Et j'ignore probablement des plans de requêtes encore meilleurs que PostgreSQL pourrait trouver.

Avez-vous essayé cela et trouvé que les performances manquaient? Si tel est le cas, ma première hypothèse serait que vous n’avez pas édité VACUUM depuis un moment. Sinon, je dois avoir mes estimations erronées pour le nombre d'articles par page ou de commentaires par article - veuillez mettre à jour avec plus de détails dans ce cas.

J'appuie la réponse de j_random_hacker. Seulement, j'éviterais de stocker l'id de l'article dans la table comments_seen_by_user, car l'id de comment devrait être globalement unique pour chaque commentaire. De plus, les index tridimensionnels (et 2D dans une moindre mesure) sont encore lents dans PostgreSQL. Essayez donc de les éviter.

Il n'y a pas vraiment de bonne manière de contourner une table d'utilisateurs_id, de valeurs comment_id pour stocker les informations sur les commentaires lus, assurez-vous simplement qu'elle possède un index unique. Quelques 10 millions de lignes dans une telle table ne posent aucun problème pour PostgreSQL, dans la mesure où il peut conserver l'index en mémoire. Vous pouvez suivre la taille de l'index (nombre de pages de 8 Ko sur le disque) avec des requêtes sur les tables système:

select relname,relpages from pg_class where relname='comments_seen_by_user_pkey';

Je serais d'accord pour adopter une approche normalisée et voir si cela fonctionne. Normalement je devrais. Cependant, vous pouvez également utiliser un déclencheur INSERT sur la table 'comment', qui met à jour un compteur de commentaires dans la table de base (c'est-à-dire l'article). Cela dépend du profil d'utilisation de ce site Web: Si les commentaires sont principalement lus (par rapport à l'ajout de commentaires), les frais généraux d'une approche à base de déclencheur devraient être amortis rapidement. Sinon, si les sites sont très chargés, la performance pourrait en souffrir.

J'opterais pour une structure de table normalisée simple et ajouterais une autre optimisation ultérieurement, lorsque vous disposez d'un profil d'utilisation raisonnable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top