Используя PHP и MySQL, у меня есть система форума, которую я пытаюсь создать. Я хочу знать, как я могу установить его так, чтобы, когда пользователь читает запись в форуме, он отображается как прочитанный JUST для этого пользователя, независимо от того, на каком форуме они находятся, пока кто-то еще не отправит на него сообщения.
В настоящее время для каждого потока у меня есть таблица с PostID, и у нее есть UserID, который отправил ее, ThreadID, чтобы связать ее с фактическим сообщением (в виде текста), а затем дату / время, которое было опубликовано.
Для списка потоков в каждом форуме есть threadID (Primary Key), ThreadName, ForumID, который принадлежит, NumPosts, NumViews, LastPostDateTime и CreateDateTime. Любая помощь?
Может храниться в другой таблице UserID, threadID, LastReadDateTime, когда пользователь читает этот поток.
if (LastPostDateTime > LastReadDateTime) you got an unread post.
К сожалению, у вас есть большие накладные расходы, при каждом чтении вы будете писать.
Традиционное решение представляет собой таблицу соединений, которая представляет собой следующее:
CREATE TABLE topicviews ( userid INTEGER NOT NULL, topicid INTEGER NOT NULL, lastread TIMESTAMP NOT NULL, PRIMARY KEY (userid, topicid), FOREIGN KEY (userid) REFERENCES users(id), FOREIGN KEY (topicid) REFERENCES topics(id) );
с lastread обновляется каждый раз, когда тема читается. При отображении списка тем, если topic.lastupdated является> topicviews.lastread, появляются новые сообщения.
Традиционное решение – мусор и убьет вашу базу данных! Не делай этого!
Первая проблема заключается в том, что запись в каждом представлении темы скоро приведет сервер базы данных на колени на занятый форум, особенно на таблицы MyISAM, которые имеют только блокировки на уровне таблицы. (Не используйте таблицы MyISAM, используйте InnoDB для всего, кроме полнотекстового поиска).
Вы можете немного улучшить эту ситуацию, только потрудившись писать через время последнего прочтения, когда в этой теме есть новые сообщения. Если topic.lastupdated <topicviews.lastread вам нечего получить, обновив значение. Тем не менее, на сильно используемом форуме это может быть бременем.
Вторая проблема – комбинаторный взрыв. В строке добавляется одна строка для каждого пользователя: всего тысяча пользователей и тысяча тем, и у вас есть потенциально миллион строк для просмотра!
Вы можете немного улучшить ситуацию, ограничив количество тем, запоминаемых для каждого пользователя. Например, вы можете удалить любую тему из таблицы представлений, когда она станет старше определенного возраста, и просто предположите, что все старые темы «прочитаны». Это обычно требует задачи очистки, которая должна выполняться в фоновом режиме.
Другие, менее интенсивные подходы включают:
Общие идеи здесь правильные, но они упустили некоторые очевидные решения проблемы масштабируемости.
@bobince: Вторая проблема – комбинаторный взрыв. В строке добавляется одна строка для каждого пользователя: всего тысяча пользователей и тысяча тем, и у вас есть потенциально миллион строк для просмотра!
Вам не нужно хранить запись в таблице «topicviews», если кто-то еще не видел этот поток. Вы просто показываете тему с непрочитанными сообщениями, если возвращается null или время last_read <last_post time. Это уменьшит количество «миллионов» строк, возможно, на порядок.
@gortok: Есть много способов сделать это, но каждый растет экспоненциально больше, когда пользователь посещает сайт.
В этом случае вы архивируете форум после n-сообщений или n-недель и, когда вы блокируете, вы очищаете таблицу «topicviews».
Мое первое предложение очевидно и не имеет недостатков. Моя вторая уменьшает удобство использования на заархивированные темы, но это небольшая цена за быстрый форум. Медленные форумы просто больно читать и публиковать.
А если честно? Вам, вероятно, не нужно будет беспокоиться о масштабируемости. Даже миллион строк действительно не так много.
Нет простого способа сделать это. Есть много способов сделать это, но каждый растет экспоненциально больше, поскольку пользователь посещает сайт. Лучшее, что вы можете сделать и по-прежнему поддерживать производительность, – это отметка времени и отметьте любые форумы, которые были обновлены со времени последнего посещения, как «непрочитанные».
Вы можете просто использовать функциональные возможности браузера пользователя и добавить последний postid в ссылку на поток вроде этого: «thread.php? Id = 12 & lastpost = 122»
Используя: посетив в своем CSS, вы можете отображать сообщения, которые пользователь уже читал, отличные от тех, которые он не читал.
У Бобейна много хороших предложений. Еще несколько возможных оптимизаций:
Написать новый «это новый?» информацию в memcached и в таблицу MySQL «ARCHIVE». Пакетное задание может обновлять «реальную» таблицу.
Для каждого пользователя сохраните флаг «все прочитанное до $ date» (для тех случаев, когда нажата кнопка «отметить все прочитанные»).
Когда что-то новое опубликовано, очистите все флаги «он был прочитан», который удерживает число «флажков» вниз, а таблица может быть просто (topic_id, user_id) – никаких временных меток.
Используемый браузер пользователя функциональности и добавьте последний идентификатор сообщения в ссылку потока. После использования: посещенного в CSS вы можете отобразить весь поток, который не был прочитан пользователем.