Помогите с организацией выборки
Вобщем, такая задача
1. есть таблица со списком контента content в ней поля:
city - id-шник города(ФК)
uid - id автора(ФК)
rate - рейтинг страницы
остальные поля щас роли не играют
2. соответсвенно табли юзеров, с именем юзера.
3. таблица друзей юзера связка uid-friend_uid
МНе нужно опстроить рейтинг пользователей по конкретному городу.
Вроде не так и сложно
Код:
SELECT u.name, c.uid, c.city, sum(c.rate) as rating FROM content c LEFT JOIN user_profile u ON c.uid=u.id WHERE c.city=1 GROUP BY c.uid ORDER BY rating DESC
Но. мне нужно рейтинг выводить в таком формате
1. Юзвер 1
2. Бзверь 2
3. Юзвер 3
......... - это не так далее, а значит что эти юзеры меня не интересуют
хх. Мой Друг Вася
......
уу. Я
.........
zz. Мой Друг Петя
Вариант вытаскивать всегда всех и потом уже просто искать нужных людей и выводить, не совсем оптимален, а точнее не оптимален.
Модификация этого варианта, хранить выборку в memcache на протяжении некоторго временит Это лучше но, тут сложный механизм дропа записей в кеше(зачем лишний раз мускуль дергать), ну или все-таки просто держать считать ее актулаьно час, к мпримеру. Но такой вариант мне тоже не очень нарвится
Что можете посоветовать?
язык PHP, субд - мускуль
Я трижды прочитал топик и не понял в чем собственно проблема заключается? Запрос не работает?
И я никак не могу придумать, как оптимизировать весь механизм формирования рейтинга для каждого юзера
При изменении рейтинга страницы сразу записывать изменение в суммарный рейтинг пользователя в специальном поле в таблице с пользователями
Рейтинг формируется по критериям, сейчас пока по Городу.
Т.е у меня контентасоздано 3 для Киева, 2 - Москвы, 5- Львова.
И я увижу себя в 3х рейтингах..
Если у меня друг создавал для Петербурга контент, то просматривая рейтинги по Петербургу я там увижу друга, но не увижу себя
parentuser , city , rating
тоже не пойдет?
Да и что эта таблица упрощает?, то что во время выборки рейтинг уже просумирован..
Не знаю.. это вопрос к спецам, сильно ли sum() жрет ресурсов?
А сколько всего записей в таблицах? И какие еще возможны критерии? Может их можно также пересчитывать каждый раз при каких-либо действиях пользователя, чтобы не шерстить потом по всем таблицам?
По поводу "жрёт ресурсов" лучше профайлера мускульного тебе никто не скажет. Если запрос реально тормозит, а не просто ловля блох, то я засунул бы просто в кеш и не парился. Если траблы с мемкешем, то воспользуйся мускулом с его memory table engine.
Вешать обновление мемкеша на действия связаные с изменением ретинга проблемно..
2RussianSpy - записей... Городов несколько десятков тысяч. но контента пока нету.. проэкт еще в продакшн не уехал...
memory table engine. ... надо почитать что оно такое
В кеш можно положить и на 10 мин )
Цитата: shaelf
В кеш можно положить и на 10 мин )
Это понятно. :) время обратно пропорционально частоте обновлению рейта.
Предположим что записей в таблице контента несколько тысяч, юзеров пару сотен, городов тоже.
Исходя из этого какой механизм будет оптимальней
напомню в результате нужно, ТОП3 юзера, мое место в рейте, место в рейте одного-трех моих друзей...
Если до завтра не решится, то вечером ещё можно будет подумать - обсудить :)
Цитата: Lone Wolf
Попробую спросить по другому..
Предположим что записей в таблице контента несколько тысяч, юзеров пару сотен, городов тоже.
Исходя из этого какой механизм будет оптимальней
Предположим что записей в таблице контента несколько тысяч, юзеров пару сотен, городов тоже.
Исходя из этого какой механизм будет оптимальней
Ну это не объемы)) не понимаю в чем вообще проблема. Если запрос тормозит (а он не должен тормозить при таких объемах) - значит запрос неверный.
А при каких обьемах начнутся проблемы? Или так, тормозить не будет при одинароном запросе, а если их несколько штук одновременно?
Да я могу это все и сам попробывать протестировать, но как по мне быстрее спросить у знающих, у тех кто сталкивался с подобными задачами, им ожет ответь - да тут будут тормоза. Делай по другому.
Если не получу однозначного ответа, то как дойду до этой задачи буду тестировать. Но согласитесь, проще за нее браться когда уже знаешь про возможные риски
Точнее без гоняния профайлером омжно ли что-то сказать, насколько он оптимален:
[highlight="sql"]
SELECT @pos as posit, rt.firstname, rt.cuid, rt.rating, rt.fuid FROM
(SELECT @pos:=0) p,
(SELECT u.firstname as firstname, c.uid as cuid, f.uid as fuid, c.city, sum(c.rate) as rating
FROM content c
LEFT JOIN user_profile u ON c.uid=u.id
LEFT JOIN friends f ON f.aid=c.uid
WHERE ( c.city=1 )
GROUP BY c.uid
ORDER BY rating DESC) rt
WHERE ( (@pos:=@pos+1)<4 OR rt.fuid=7 OR rt.cuid=7 )
[/highlight]
т.е. я выбираб весь рейтинг: имя, рейтинг, идшник юзера, потом из этих результатов выбираю только себя, друзей и запустив итератор который дает мне номер строки(читай позицию в рейтинге) в фильтр добавляю только первые три
Итого что я этим получил
1. Мне не нужно вытягивать в скрипт весь рейтинг
2. Потом перебором сравнивать нужные идшники юзеров
3. Существенно усложнился запрос
Вот теперь интересно стоит ли шкурка вычинки...
Просто сложно сказать что именно вам надо делать не зная всей архитектуры.
И опять таки не зная архитектуры и конфигурацию железа, где это все будет работать, точно сказать с какого момента начнутся проблемы невозможно.
Как говорят мастера дзеня - "Преждевременная оптимизация - корень всех зол" или из 37Signals: "Пока проблема не возникла, её просто не существует" ) Нужно реально смотреть на сколько допустима нагрузка на машину.