Comments 40
можно попробовать держать отдельную таблицу (или просто дополнительную колонку в таблице пользователей) с текущим рейтингом каждого пользователя. когда происходит какое-либо событие, которое может повлиять на рейтинг, он пересчитывается и записывается в эту таблицу (колонку).
т.о. в любой момент мы знаем актуальный рейтинг всех пользователей и нам надо лишь сделать select с order by
т.о. в любой момент мы знаем актуальный рейтинг всех пользователей и нам надо лишь сделать select с order by
+1
Почему-то мне кажется что надо будет еще проще — сделать select count(*) where rank>«текущий ранг пользователя». Думаю тут даже может быть использован поиск только по индексу, хотя не уверен.
+2
Да, по-моему это оптимальный вариант, а поиск только по индексу — имхо будет использован, почему нет? Если есть индекс на поле rank — какие еще данные нужны субд чтобы посчитать кол-во записей?
+1
+1
rank в отдельное поле, которое обновлять по нужной формуле через определенный промежуток времени, на rank — индекс, и select count(*)… where rank > user_rank. Это и будет позицией юзера в рейтинге
rank в отдельное поле, которое обновлять по нужной формуле через определенный промежуток времени, на rank — индекс, и select count(*)… where rank > user_rank. Это и будет позицией юзера в рейтинге
+1
Начал проверять и наткнулся на проблему юзеров с нулевым рейтингом.
Рассмотрим пример, есть юзеры с рейтингом (1)10 (2)7 (3)5 (4)3 (5)1 (6)0 (7)0 (8)0 (9)0
При выборке where rank > 0 мы получим в ответ — 5 для всех трёх последних юзеров. То же самое выйдет со всеми повторяющимися значениями.
Рассмотрим пример, есть юзеры с рейтингом (1)10 (2)7 (3)5 (4)3 (5)1 (6)0 (7)0 (8)0 (9)0
При выборке where rank > 0 мы получим в ответ — 5 для всех трёх последних юзеров. То же самое выйдет со всеми повторяющимися значениями.
0
Это, мне кажется, вопрос религии.
Если у них одинаковый рейтинг, то почему бы им не иметь одинакового места в таблице?
Если у них одинаковый рейтинг, то почему бы им не иметь одинакового места в таблице?
0
Пусть каждый думает что первый из 5 — он :)
0
И как это должно выглядеть в общей таблице?
Выглядеть-то оно будет нормально, но если их, одинаковых, больше одной страницы, то ссылаться корректно уже не получится.
Выглядеть-то оно будет нормально, но если их, одинаковых, больше одной страницы, то ссылаться корректно уже не получится.
0
См. UPD 2
0
Ну тогда например такое развитие предложенного выше варианта:
— получаем рейтинг пользователя
— получаем кол-во пользователей у которых рейтинг больше
— получаем кол-во злодеев, который обходят текущего пользователя по позиции в рейтинге, хотя кол-во рейтинга у них тоже, для актуальной позиции складываем результаты 2 и 3 запроса.
Ну и соот-но в общем списке пользователей с одинаковым рейтингом нужно будет сортировать именно по тому полю, которое используется для определения позиции в третьем запросе (в моем случае user_id)
SELECT rating FROM table WHERE user_id =?
— получаем рейтинг пользователя
SELECT COUNT(*) FROM table WHERE rating > current_user_rating
— получаем кол-во пользователей у которых рейтинг больше
SELECT COUNT(*) FROM table WHERE rating = current_user_rating AND user_id > current_user_id
— получаем кол-во злодеев, который обходят текущего пользователя по позиции в рейтинге, хотя кол-во рейтинга у них тоже, для актуальной позиции складываем результаты 2 и 3 запроса.
Ну и соот-но в общем списке пользователей с одинаковым рейтингом нужно будет сортировать именно по тому полю, которое используется для определения позиции в третьем запросе (в моем случае user_id)
0
Хорошая идея, спасибо.
А бд по умолчанию, одинаковых злодеев будет по id сортировать?
Если сделать выборку SELECT * FROM `table` WHERE 1 ORDER BY `rating`
А бд по умолчанию, одинаковых злодеев будет по id сортировать?
Если сделать выборку SELECT * FROM `table` WHERE 1 ORDER BY `rating`
0
Да, изначально сортировка будет по первичному ключу, раз у вас в таблице есть id — то это наверное он и есть :)
0
В общем случае это не так, не учите плохому.
0
Да, действительно не так, я ошибся, хотя проверял перед тем как написать, но похоже мой тогдашний результат оказался совпадением, при сортировке по другому полю действительно никакой сортировки по первичному ключу нет.
0
Тогда похоже для предложенного мной понадобится выборка
SELECT * FROM `table` ORDER BY `rating`, `id`
SELECT * FROM `table` ORDER BY `rating`, `id`
0
А это уже мы начали тратить ресурсы. Ибо двойная сортировка — не есть хорошо.
0
Да это понятно… в общем я разобрался почему разнятся мои вчерашние и сегодняшние результаты, когда на поле rating висит индекс — результат отдается в соот-ии с первичным ключем, без индекса — в разнобой, но без индекса тут вообще никуда :) в общем тут конечно нужно углубленнее разбираться, хранятся-ли индексы с изначальной сортировкой по первичному ключу или нет.
+1
Насколько я смог понять всю эту красоту: en.wikipedia.org/wiki/B-tree данные в такого рода деревьях (которые собственно и используются в MySQL-индексах по числовым полям) хранятся сортированными вдоль и поперек, если вкратце:
B-tree is a tree data structure that keeps data sorted
+1
Ага, понято. То есть первичный ключ влияет на построение индекса по рейтингу. И если индекс есть, то он вторично упорядочен по первичному ключу, а если нет, то…
А при отдаче без индеска такая же структура случаем не формируется?
А при отдаче без индеска такая же структура случаем не формируется?
0
Как я смог понять принцип работы всей этой гадости — нет.
Механизм сортировки набирает значения для сортировки в буфер, сортирует и сохраняет на диск, затем когда все данные сохранены — склеивает различные буферы между собой и получает общий результат.
В случае с прямым чтением из таблицы — он будет читать значения по порядку, добавлять в буфер и сортировать, сортировать есс-но только по рейтингу, и результат в итоге выйдет отсортированным только по рейтингу.
В случае-же с индексом — механизм сортировки будет читать значения для сортировки из индекса, где они уже упорядочены, первично по рейтингу, вторично по первичному ключу, и соот-но изменять порядок их следования ему не потребуется, и данные в буфере останутся в таком-же порядке что и были считаны. Ну и соот-но если сортировка производится в обратном порядке (ORDER BY rating DESC) — данные из индекса будут считаны в обратном порядке, и вторичная сортировка по первичному ключу также будет в обратном порядке.
Механизм сортировки набирает значения для сортировки в буфер, сортирует и сохраняет на диск, затем когда все данные сохранены — склеивает различные буферы между собой и получает общий результат.
В случае с прямым чтением из таблицы — он будет читать значения по порядку, добавлять в буфер и сортировать, сортировать есс-но только по рейтингу, и результат в итоге выйдет отсортированным только по рейтингу.
В случае-же с индексом — механизм сортировки будет читать значения для сортировки из индекса, где они уже упорядочены, первично по рейтингу, вторично по первичному ключу, и соот-но изменять порядок их следования ему не потребуется, и данные в буфере останутся в таком-же порядке что и были считаны. Ну и соот-но если сортировка производится в обратном порядке (ORDER BY rating DESC) — данные из индекса будут считаны в обратном порядке, и вторичная сортировка по первичному ключу также будет в обратном порядке.
+1
Или не через промежуток времени, а непосредственно в момент изменения какой-нибудь характеристики юзера, влияющей на рейтинг
0
UFO just landed and posted this here
Может быть, я не спорю. Но решение является не оптимальным по своей сути. Оно тратит ресурсы на избыточность данных, которая в большенстве случаев и не понадобиться.
Я к тому, что зачем обновлять рейтинг всех пользователей каждые 5 минут, когда за 5 минут этим рейтингом даже половина никогда не воспользуется?
Я к тому, что зачем обновлять рейтинг всех пользователей каждые 5 минут, когда за 5 минут этим рейтингом даже половина никогда не воспользуется?
0
UFO just landed and posted this here
Я не спорю о производительности, да и портала ещё нет, только разрабатываю.
Дело в том, что в тексте я подразумивал вычисление и сохранение позицый, что означает апдейт всех полей. Вы собственно только подтвердили, что это лишние ресурсозатраты.
На самом деле я считаю, что решение Eyes — оптимально.
Дело в том, что в тексте я подразумивал вычисление и сохранение позицый, что означает апдейт всех полей. Вы собственно только подтвердили, что это лишние ресурсозатраты.
На самом деле я считаю, что решение Eyes — оптимально.
0
UFO just landed and posted this here
То что MySQL настолько крут — еще не означает что нужно забив на все болт работать с ним как придется, выборку за 0.1 секунду нельзя назвать «призадумался», однако если есть вариант сделать аналогичную за 0.001 секунду — то следует уж наверное предпочесть ее. Столько людей бъется на тем чтобы оптимизировать работу с БД в высоконагруженных проектах — а тут оказываецца нафиг оно все, MySQL сам все разрулит, жаль только серверные скрипты он сам не пишет.
+1
UFO just landed and posted this here
Ну так вот мы и пришли к теме топика :) человек попросил подсказать как ему лучше сделать запрос к БД не через жёпу и правой ногой :) ему подсказали :)
А насчет выбрать из базы 10 тысяч строк — это имхо как раз таки запрос над которым в теории неплохо-бы задуматься, потому как кол-во пользователей будет увеличиваться, кол-во их рейтингов соот-но тоже, и кол-во запросов на получение собственного рейтинга тоже, нагрузка будет расти с двух сторон, дойдет-ли проект до кол-ва пользователей больше 10к это конечно тот еще вопрос, но зачем оставлять на самотек потенциальную проблему, которую изначально можно красиво и внятно решить.
А насчет капч — я честно говоря не понял какое они имеют отношение к изначальной теме разговора, но в чем-то я конечно согласен, обычные капчи сейчас приносят мало пользы, по мне так еще имеют право на жизнь капчи с осмысленным содержимым, где вместо «dtrge» написано «сложи 2 и 2», в конце концов если посетитель не умеет читать/считать — то пользы от него, как от потенциального клиента — все равно нет :)
А насчет выбрать из базы 10 тысяч строк — это имхо как раз таки запрос над которым в теории неплохо-бы задуматься, потому как кол-во пользователей будет увеличиваться, кол-во их рейтингов соот-но тоже, и кол-во запросов на получение собственного рейтинга тоже, нагрузка будет расти с двух сторон, дойдет-ли проект до кол-ва пользователей больше 10к это конечно тот еще вопрос, но зачем оставлять на самотек потенциальную проблему, которую изначально можно красиво и внятно решить.
А насчет капч — я честно говоря не понял какое они имеют отношение к изначальной теме разговора, но в чем-то я конечно согласен, обычные капчи сейчас приносят мало пользы, по мне так еще имеют право на жизнь капчи с осмысленным содержимым, где вместо «dtrge» написано «сложи 2 и 2», в конце концов если посетитель не умеет читать/считать — то пользы от него, как от потенциального клиента — все равно нет :)
+1
Тут еще есть одна подзадача:
как тогда будет выглядеть вариант вывода списка участников, например читающих один блог, или с одним увлечением?
Пользователи:
ID Rating
1 — 123
2 — 512
3 — 124
5 — 123
6 — 444
7 — 983
8 — 321
9 — 0
10 — 2
####################
Этот блог читают:
####################
User 1
User 3
User 6
User 7
Вариант select count(*) where rank>«текущий ранг пользователя» уже не подойдет.
Самый простой вариант — это кешируемая на определенное время картинка как тематический индекс цитирования Яндекса
как тогда будет выглядеть вариант вывода списка участников, например читающих один блог, или с одним увлечением?
Пользователи:
ID Rating
1 — 123
2 — 512
3 — 124
5 — 123
6 — 444
7 — 983
8 — 321
9 — 0
10 — 2
####################
Этот блог читают:
####################
User 1
User 3
User 6
User 7
Вариант select count(*) where rank>«текущий ранг пользователя» уже не подойдет.
Самый простой вариант — это кешируемая на определенное время картинка как тематический индекс цитирования Яндекса
0
Чегот не совсем понял про ТИЦ, можно по подробнее?
0
Это уход от прямых запросов при генерации страницы.
Просто в то место, где должно быть выведено место конкретного участника, вставляется картинка
####################
Этот блог читают:
####################
User 1 [img src="/rating_1.jpg"]
User 3 [img src="/rating_3.jpg"]
User 6 [img src="/rating_6.jpg"]
User 7 [img src="/rating_7.jpg"]
сама же картинка генерируется скриптом при первом обращении (по принципу select count(*) where rank>«текущий ранг пользователя» или любому другому), в скрипте устанавливается нужный Expire, и когда она будет неактуальна — перегенерируется заново. Все под контролем.
По-моему вариант.
Просто в то место, где должно быть выведено место конкретного участника, вставляется картинка
####################
Этот блог читают:
####################
User 1 [img src="/rating_1.jpg"]
User 3 [img src="/rating_3.jpg"]
User 6 [img src="/rating_6.jpg"]
User 7 [img src="/rating_7.jpg"]
сама же картинка генерируется скриптом при первом обращении (по принципу select count(*) where rank>«текущий ранг пользователя» или любому другому), в скрипте устанавливается нужный Expire, и когда она будет неактуальна — перегенерируется заново. Все под контролем.
По-моему вариант.
0
А имеет ли вообще смысл выводить везде где только можно положение пользователя в рейтинге в сравнении с другими пользователями? Если на то пошло, то гораздо более показательнее будет выводить не место, а само значение ранга.
А то разница между 3 пользователями:
User1 — 1 место
User3 — 10 место
User22 — 100 место
Будет менее очевидна чем:
User1 — 97 баллов
User3 — 88 баллов
User22 — 55 баллов
Хотя конечно зависит от специфики приложения.
А то разница между 3 пользователями:
User1 — 1 место
User3 — 10 место
User22 — 100 место
Будет менее очевидна чем:
User1 — 97 баллов
User3 — 88 баллов
User22 — 55 баллов
Хотя конечно зависит от специфики приложения.
+1
Sign up to leave a comment.
Articles
Change theme settings
Алгоритм рейтинг листа.