Прямой эфир

lelik17

Новичок
Стоит задача. Вывести посление события на сайте. Никак не соображу ким должен быть sql запрос. Есть несколько таблиц:

comments (id, date, user_id)
posts (id, date, user_id)
ocenki (id, date, user_id)

вот на из них то и нужно вывести что-то вроде:

1. 20.03.2011 18:37 - Вася оставил комментарий №id
2. 20.03.2011 15:22 - Женя разместил пост №id
3. 19.03.2011 14:01 - Таня поставила оценку

Подскажите каким должен быть запрос к базе.
 

shelestov

я тут часто
А как отличить потом что из этого пост, а что комментарий?
(select id, date, user_id, 'comments' from posts)
union
(select id, date, user_id, 'posts' from posts)
union
(select id, date, user_id, 'ocenki' from ocenki)
......

Таким образом у каждой записи будет индификатор. У постов posts, у комментарием comments и т.д.
 

zerkms

TDD infected
Команда форума
shelestov
mysql будет очень невесело объединять в памяти (а потом и на винте, когда память кончится) 3 таблицы, при том что ты не можешь сделать вложенный LIMIT, а потом ещё и сортировать эту всю массу через скан, без индексов.

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

(Революционная альтернатива - отдельно для списков поднять mongodb, и создать коллекцию там, вместо таблицы mysql)
 

shelestov

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

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

(Революционная альтернатива - отдельно для списков поднять mongodb, и создать коллекцию там, вместо таблицы mysql)
Можно так же все это сваливать в memcache или redis, одна херня :)

Многое зависит от объемеов данных. Если их не много и индексы правильно выстроены, то все и так будет летать, хотя я все таки настаиваю на кешировании.
 

zerkms

TDD infected
Команда форума
shelestov
В мемкэш валить не получится, потому что не персистентный, и потому что при добавлении записи в одну из таблиц - снова выполнять этот неподъёмный запрос.

По поводу индексов - попробуй на основе твоего наброска напиши запрос, который будет использовать индексы правильно? :)

Так что настаиваю не на кешировании, а на переносе персистентных данных :)
 

shelestov

я тут часто
shelestov
В мемкэш валить не получится, потому что не персистентный, и потому что при добавлении записи в одну из таблиц - снова выполнять этот неподъёмный запрос.

По поводу индексов - попробуй на основе твоего наброска напиши запрос, который будет использовать индексы правильно? :)

Так что настаиваю не на кешировании, а на переносе персистентных данных :)
В задаче не указан ни объем данных, ни частота их обновления. Если объем реально большой, как и частота обновления данных, тогдабудет правильным организовать отдельную таблицу в том же MySQL, либо использовать какую нибудь key-value базу, например redis.
 

zerkms

TDD infected
Команда форума
shelestov
Упс, оказывается mysql (уже?) умеет и order by и limit в "подзапросах"...

Интересно, а почему я думал что не умеет :-S Наверное потому что у оракла ограничение на сортировку в запросах с UNION

А по поводу K-V - я всё таки настаиваю на mongodb (который уже не КВ, но более подходящий для задачи, чем редиска)
 

shelestov

я тут часто
А по поводу K-V - я всё таки настаиваю на mongodb (который уже не КВ, но более подходящий для задачи, чем редиска)
Ну это уже на вкус и цвет, и требований конкретной задачи.

Упс, оказывается mysql (уже?) умеет и order by и limit в "подзапросах"...
По-моему давненько уже. http://phpclub.ru/mysql/doc/union.html
 

Вурдалак

Продвинутый новичок
shelestov, затем, что так удобнее и проще, чем возиться с этим говном. И правильнее, если хочешь. Я как-то по неопытности и лени попытался раньше сделать с UNION — теперь ни за что.
 

shelestov

я тут часто
shelestov, затем, что так удобнее и проще, чем возиться с этим говном. И правильнее, если хочешь. Я как-то по неопытности и лени попытался раньше сделать с UNION — теперь ни за что.
Возможно.
Но большого пройгрыша в производительности не будет, если данных не сильно много.
Опять же можно кешировать, а при добавлении/удалении/изменении данных сбрасывать кеш.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Хотел расписать тут то, как у нас сделан newsfeed, но мне стало лень) В общем случае все, что нужно - таблица newsfeed, в которой прописано entity_id - id элемента, над которым произошло какое-то действие, поле user_id - тот, кто действие сделал, и поля типа type и action, в них в виде int данных пишутся типы действий, type=1 - модуль новостей, action=1 - добавление. Далее идут жестокие, но весьма шустрые JOIN необходимых таблиц.
 

zerkms

TDD infected
Команда форума
c0dex
Все так делают :) Решение не уникальное. Хотя вариант со schema-less document oriented хранилищем поинтереснее будет :-P
 

lelik17

Новичок
Всем спасибо, разобрался. Сделал через UNION с ограничением в 50 событий. Т.к. нагрузка на эту страницу планируется не большая, думаю пойдёт.
 

lelik17

Новичок
Только сейчас заметил, что возникла проблема.
Запрос:

union
(select id, date, user_id, 'posts' from posts)
union
(select id, date, user_id, 'ocenki' from ocenki)
union
(select id, date, user_id, 'voprosi' from voprosi)
ORDER BY date DESC LIMIT 50

он сортирует по дате, при этом не обращает внимание на время (поле date - это DATETIME). В результате события отображаются не в хронологическом порядке. Как лечить?
 
Сверху