PHP/MySQL-активность (например, Facebook)
-
11-09-2019 - |
Вопрос
Это может быть волосатый вопрос, но.Скажи, что у меня есть
Followers:
-user_id
-follower_id
Activities:
-id
-user_id
-activity_type
-node_id
Отследить активность пользователей довольно легко.Но как лучше всего добиться активности подписчиков?Подвыбор?Кажется, что это невероятно медленно, поскольку пользователи получают все больше и больше подписчиков.Есть идеи, как это ускорить?
Кроме того, на более концептуальном уровне.Как работает группировка.Все это делается с помощью одного запроса?Или все данные о деятельности собираются, а затем сортируются и группируются на стороне PHP?
Пользователи X, Y и Z выполняли деятельность, пользователь J выполнил 3 активности B
Решение
Подзапросы часто работают медленнее, чем JOIN, но это действительно зависит от того, что именно вы с ними делаете.Чтобы ответить на ваш главный вопрос, я бы получил данные о подписчиках с помощью JOIN:
SELECT * FROM followers f
LEFT JOIN activities a ON f.follower_id=a.user_id
WHERE f.user_id=$followedPerson
Предполагается, что таблица подписчиков представляет пользователя с user_id
, и тот, кто следует за ними с follower_id
это бывает user_id
в таблице пользователей также.
Этого никогда не будет невероятно медленно, пока у вас включен индекс followers.user_id
.Однако объем данных, которые может вернуть такой запрос, может оказаться больше, чем вы действительно хотите иметь дело.Вам необходимо определить, какие виды активности ваше приложение будет показывать, и попытаться соответствующим образом отфильтровать их, чтобы не делать огромные запросы все время, а использовать лишь небольшую часть возвращаемых результатов.
Извлекать данные и группировать их на стороне PHP — это нормально, но если вы вообще можете избежать их выбора, вам будет лучше.В этом случае я бы, наверное, добавил ORDER BY f.follower_id,activity_date DESC
, предполагая, что дата существует, и попытайтесь придумать еще несколько критериев фильтрации для таблицы активности.Затем я перебирал строки PHP, выводя данные, сгруппированные по последователям.
Другие советы
Журнал активности потенциально может содержать очень большое количество записей, поскольку обычно в нем отражается активность текущего пользователя и действий всех его друзей.Если вы присоединяетесь к различным таблицам, а у пользователя сотни друзей, потенциально может быть извлечено много данных.
Один из подходов состоит в том, чтобы денормализовать данные и рассматривать их как один большой журнал, в котором все записи, которые должны появиться на странице журнала активности пользователя, будут храниться в таблице журнала активности этого пользователя.Например, если у пользователя A есть два друга, пользователь B и пользователь C, когда пользователь A что-то делает, создаются три записи журнала активности:
record 1: "I did this" log for user A
record 2: "My friend did this" log for user B
record 3: "My friend did this" log for user C
Вы получите дубликаты, но это не имеет особого значения.Выбор выполняется быстро, поскольку он взят из одной таблицы и индексируется только по идентификатору пользователя.И, скорее всего, вы будете вести таблицу журнала активности (т.удалять записи старше 1 месяца).
Таблица журнала активности может выглядеть примерно так:
-id
-user_id (user who's activity log this is)
-action_user_id (user who took the action, or null if same as user_id)
-activity_type
-date
Выбрать все недавние журналы активности для одного пользователя будет легко:
SELECT * from activity_log WHERE user_id = ? ORDER by date DESC LIMIT 0,50
Чтобы сделать этот подход действительно эффективным, вам необходимо иметь достаточно информации в одной таблице журнала активности, чтобы не требовалось никаких дальнейших выборок.Например, вы можете сохранить необработанное сообщение журнала, а не создавать его на лету.
Я не знаю, правильно ли я понял, что вам нужно, но я бы попробовал этот выбор, если я прав, вы должны получить все активности для всех подписчиков #USERID#
SELECT a.* FROM Activities AS a
INNER JOIN Followers AS f1
ON a.user_id = f1.follower_id
WHERE f1.user_id = #USERID#