2010-09-29 10 views
7

D'accord, un autre problème intéressant sur Route 50.Quel est le moyen le plus efficace pour créer un système d'ampoule de forum (non lu)?

Nous avons voulu mettre en œuvre un véritable forum système lightbulb où les messages qui sont lus par un utilisateur (après le compte de l'utilisateur est créé) montrent que non lu jusqu'à ce que l'état est effacé ou jusqu'à ce que l'utilisateur les lise.

Nous avons pensé que le moyen le plus simple et le plus simple de le faire serait d'implémenter une table de messages non lus.

Les colonnes sont: user_id, board_id, thread_id, post_id, timestamp et hidden

Cela fonctionne très bien et très rapidement pour voir quels conseils/fils/messages non lus (et les reliant) par utilisateur , mais il est très lent pour un utilisateur de poster sur le forum, même si une seule requête SQL est en cours d'exécution:

INSERT IGNORE INTO `forums_lightbulb` SELECT `id`,'x','x','x',UNIX_TIMESTAMP(),0 FROM `users` 

Je suis sûr que cela est le résultat d'avoir 3065 des comptes d'utilisateurs. Comment puis-je accélérer ce processus? Je préférerais garder le système aussi en temps réel que possible.

Remarque importante: Veuillez limiter vos réponses à un environnement d'hébergement partagé sans budget supplémentaire. Nous sommes limités à PHP et MySQL 5.1.53-log

+0

Si vous pouviez vous voulez utiliser des filtres bloom – amirouche

Répondre

9

Il conserve une table qui marque pour chaque thread et chaque forum lorsque la dernière fois un utilisateur l'a ouvert. Et utilise cela pour déterminer s'il y a des messages non lus.Il permet un schéma d'utilisation du stockage Utilisateurs * Sujets + Utilisateurs * Forums tout en permettant une vérification avec des requêtes assez simples et rapides.

Vous pouvez voir comment cela fonctionne à partir de la structure de la base de données.

# Table: 'phpbb_forums_track' 
CREATE TABLE phpbb_forums_track (
    user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, 
    PRIMARY KEY (user_id, forum_id) 
) CHARACTER SET `utf8` COLLATE `utf8_bin`; 

# Table: 'phpbb_topics_track' 
CREATE TABLE phpbb_topics_track (
    user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, 
    PRIMARY KEY (user_id, topic_id), 
    KEY topic_id (topic_id), 
    KEY forum_id (forum_id) 
) CHARACTER SET `utf8` COLLATE `utf8_bin`; 
+0

C'est peut-être ce que je cherche! Je vous remercie! Je vais récompenser la prime à moins que quelqu'un arrive avec une meilleure réponse, mais je suis sûr que c'est ce que j'essayais de comprendre! – Navarr

+1

C'est ce que le logiciel open source est juste? Apprendre les uns des autres: D – Beanow

1

En lecture:

insert into read_articles(user_id, article_id); 

Sur l'affichage:

SELECT a.*, r.user_id FROM articles a 
LEFT OUTER JOIN read_articles r ON (a.article_id = r.article_id and r.user_id = $user_id) 
WHERE (article_filter, like forum or thread id, or whatever) 

Sur votre jeu de résultats, si user_id est non nul, ils » J'ai lu l'article. Sinon, ils ne l'ont pas fait.

Index selon le cas. Serveur chaud avec des biscuits et de la confiture.

+0

Ceci est vraiment un peu la manière inverse que je voulais gérer cela .. – Navarr

4

Désolé de le dire, mais la solution proposée dans la question est un design non scalable.

Je regardais dans ce problème sur here, qui a eu une discussion décente sur elle (avant que je me suis présenté). Jetez un coup d'oeil là-bas. Dans votre cas, stocker des enregistrements U * M pour suivre des messages "non lus", où U est le nombre d'utilisateurs et M est le nombre de messages, serait très rapidement hors de contrôle. En effet, son efficacité optimale exige que tous les utilisateurs lisent tous les messages (et la plupart des utilisateurs ne se soucient pas de tout, car la plupart du temps sur un forum c'est du bruit). Moyenne des cas, peut-être 20% des utilisateurs ont lu 100% des messages, mais 80% ont lu près de 0% des messages et ne liront jamais le reste. Cela signifie que vous êtes obligé de stocker 0.8 * U * M, avec U et M n'augmente que de façon géométrique. Aucune quantité d'indexation ne résoudra cela.

La réponse @ will-hartung précédente a l'approche la plus efficace. Je vois que c'est assez vieux, et j'espère que vous avez trouvé une meilleure solution en attendant. Ce que PHPBB fait est un moyen très rapide de le faire.

+0

J'ai théorisé une meilleure solution, qui est un mélange d'horodatages et de stockage des messages lus, ou quelque chose comme cette. Je ne l'ai pas complètement planifié. En attendant, cependant, j'ai juste désactivé le système d'ampoule. – Navarr

2

Voici la façon la plus efficace:

  1. ont une table appelée read_threads qui stocke les thread_id et user_id
  2. ont une colonne dans la table users appelée mark_read_date qui stocke la date à laquelle l'utilisateur cliqué sur le lien mark all threads read dans votre forum
  3. afin de déterminer si un thread est lu, votre requête va vérifier si elle est dans leTable, ou si son last_post_date (la date du dernier message lui a été faite) est plus ancienne que la usersmark_read_date

Il est important que vous supprimez également toutes les lignes de la table read_threads lorsqu'un utilisateur clique sur le lien mark all threads read dans votre forum.

Questions connexes