Лента активности с PHP MySQL - PullRequest
4 голосов
/ 16 сентября 2011

Я создаю некий "поток / канал активности" с использованием PHP и MySQL.

Я получил одну таблицу для потока, которая просто хранит тип активности и метку времени. Затем мне нужно найти фактические данные для действия, которые можно найти в различных таблицах (в зависимости от вида деятельности). Поток должен быть в состоянии обрабатывать сотни пользователей, и поэтому мне нужно, чтобы он работал хорошо. Варианты, которые я получил:

  • Получить таблицу потоков - перебрать в PHP какой-то переключатель и затем вызвать SQL для соответствующих данных активности (для каждого действия). (Slow)
  • Составьте одно большое SQL-предложение с несколькими объединениями, получая все данные об активности в одном запросе. Все еще выполняю переключение в PHP, но без необходимости повторного вызова SQL. (Это медленно для больших столов?)
  • Использование некоторых видов представлений с MySQL - я раньше этого не делал.
  • Использование нескольких вызовов SQL для получения всех данных о деятельности и их сохранения в массивах PHP, а затем переключение.

У меня есть другие варианты? Каков наилучший подход с точки зрения производительности?

Ответы [ 4 ]

4 голосов
/ 21 сентября 2011

Вы можете выполнить управляемый данными JOIN с помощью одного запроса.По сути, вы должны JOIN каждый необходимый подтаблицу, а затем, используя псевдонимы, выбрать содержимое из таблицы, которая вам нужна.Предполагая, что 1 - это action_drink, 2 - activity_eat, а 3 - activity_sports, и у всех подтаблиц есть столбец content, который вы хотите получить:

SELECT a.`timestamp`,
    CASE a.`activity_type`
        WHEN 1 THEN ad.`content`
        WHEN 2 THEN ae.`content`
        WHEN 3 THEN asp.`content`
    END AS content
FROM activities AS a
LEFT JOIN activity_drink AS ad ON (ad.`activity_id` = a.`activity_id`)
LEFT JOIN activity_eat AS ae ON (ae.`activity_id` = a.`activity_id`)
LEFT JOIN activity_sports AS asp ON (asp.`activity_id` = a.`activity_id`)

Это в основном приведет к денормализации ваших таблиц в выбранное время.Вы также можете преобразовать его в VIEW для удобства доступа.Это не должно быть слишком дорого, при условии, что вы правильно настроили внешние ключи, идентификаторы и / или UNIQUE индексы (MySQL не заметит совпадения строк в таблице и «проигнорирует это» - выбрав строку NULL).Я не проверил это должным образом, так как у меня нет никаких данных, и я должен был предположить, но фрагмент должен быть в основном функционирующим.

Однако я хотел бы отметить, что лично я опасаюсь делать этоуправляемые данными соединения.Правильный способ нормализации в этом случае - найти самый большой общий набор атрибутов и поместить их в таблицу activities.При необходимости вы можете добавить дополнительную информацию в соседние таблицы.Однако, вообще говоря, если несколько таблиц используют одни и те же данные, вам, вероятно, следует переместить их в основной столбец, если в этом нет крайней необходимости.

0 голосов
/ 26 января 2018

Мое реализованное решение имеет 7 различных типов типов контента, которые хранятся в отдельных таблицах, но у меня есть 1 таблица действий / фидов .

Мое решение - Используя mySQL5.7, я использую поле JSON . У меня есть задание, которое выбирает различные типы контента и вставляет строку в таблицу действий и, используя mysql JSON_OBJECT () , сохраняет эти данные как json в столбце данных, а затем мое приложение управляет этим json. и отображает как следует. Данные JSON содержат только необходимые данные для этого типа контента, поэтому нулевые значения отсутствуют

  • id | contentType | данные (JSON) | создано | статус

Таким образом, это означает, что у меня нет внутренних объединений, нет ни одной масштабируемой таблицы с множеством пустых полей.

Я легко смог добавить больше типов контента, ничего не меняя.

0 голосов
/ 19 июня 2013

Это поздний ответ, но если фид активности является частью более крупного приложения, возможно, имеет смысл использовать внешний сервис, такой как Collabinate (http://www.collabinate.com).

0 голосов
/ 16 сентября 2011

если поток активности не слишком длинный (несколько записей, а не тысячи), я бы пошел только на один запрос, если таблицы проиндексированы правильно, запрос должен быть достаточно быстрым.В случае, если вы можете создавать объединения со своими таблицами, я думаю, этот запрос не должен быть таким дорогим.

SELECT * FROM (
  SELECT * FROM stream 
    INNER JOIN type1 ON stream.id = type1.stream_id
  LIMIT 50

  UNION

  SELECT * FROM stream 
    INNER JOIN type1 ON stream.id = type1.stream_id
  LIMIT 50

  UNION

  ...
)
ORDER BY stream.timestamp_field
LIMIT 50

В качестве другого решения, если у вас мало таблиц типов, вы можете сделать запросдля каждого типа таблицы, а затем объединить результаты.Но вам придется заказать объединенные результаты с PHP.

$sql1 = "SELECT * FROM stream INNER JOIN type1 ON stream.id = type1.stream_id";
$sql2 = "SELECT * FROM stream INNER JOIN type2 ON stream.id = type2.stream_id";
...

Какого размера результаты вы хотите получить ??как вы хотите заказать результаты ??возможно, производительность не является проблемой, ограничивая результаты вашего запроса.

...