首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现排行榜

实现排行榜
EN

Stack Overflow用户
提问于 2010-01-03 03:44:17
回答 4查看 4.7K关注 0票数 4

Users on my site为说唱歌词创建注释(example)。我想创建一个排行榜来奖励那些创建了最多注释的人。

排行榜应该跟踪每个用户总共创建了多少注释,以及他在过去的一周、一天等创建了多少注释。

我在实现整体排行榜方面没有问题:

代码语言:javascript
复制
@users = User.all

<table>
  <tr>
    <th>Contributor</th>
    <th>Annotations</th>
  </tr>
    <% @users.sort_by{|u| u.annotations.size }.reverse.each do |u| %>
      <tr>
        <td><%= u %></td>
        <td><%= u.annotations.size %></td>
      </tr>
    <% end %>
</table>

但是当我尝试实现(比方说)每日记分板时,我在重复代码,并且操作非常慢(因为它必须迭代内存中的每个注释,而不是依赖于数据库排序/计数):

代码语言:javascript
复制
<table>
  <tr>
    <th>Contributor</th>
    <th>Annotations</th>
  </tr>
    <% @users.sort_by{|u| u.annotations.select{|a| a.created_at > 1.day.ago }.size }.reverse.each do |u| %>
      <tr>
        <td><%= u %></td>
        <td><%= u.annotations.select{|a| a.created_at > 1.day.ago }.size %></td>
      </tr>
    <% end %>
</table>

实现每日/每周记分板的最佳方式是什么?

EN

回答 4

Stack Overflow用户

发布于 2010-01-03 04:15:38

排行榜作为一个整体的实现是一件痛苦的事情。根据我的经验,实际的实现是相当简单的,只是它们很难扩展。通常,你会发现自己不得不运行许多数据库查询,这对数据库来说是非常密集的。要处理每日/每周报告,您可能会查询日期时间列,但这意味着您在该列上有一个索引。该索引实际上只对排行榜查询有用,它会使该表上的所有其他写操作付出代价,因为必须重新计算索引。

另一种方法是按计划的时间间隔生成统计数据,然后将该数据写入一个单独的表,该表供排行榜查询使用。例如,你有一个后台作业,每晚你运行一个查询(这可能是一个昂贵的,因为它不使用datetime索引,但因为它只运行一次,通过一个后台作业的费用是"ok"),该查询反过来写到一个统计表,确实有一个索引的datetime列,然后你重写您的排行榜页面,以达到您的预先计算的统计数据。根据您的需要,您可能还会让cron脚本执行其他数据转换和预计算,因此排行榜页面必须尽可能少地进行计算。

在这一点上,您的排行榜页面正在工作,虽然它命中一个带有索引的表,但它仍然必须读取大量的行。这是假设你有不错的流量。让索引查询命中每页上的大量行仍然是很昂贵的。因此,现在您可以考虑实现页面缓存,也许将数据存储在memcached中。也就是说,由于每天排行榜数据至少每天都会发生变化,根据定义,在每个页面视图上重新运行这些DB查询的代价很高。在memcached中缓存日常数据更有意义,每个页面视图只访问memcached。

所以你可以看到这是一个进化的过程。如果您的流量低于,那么您可以不使用单独的表,只在datetime列上建立索引。运行和,计数和平均值可能是可以的。但它不能扩展。因此,您必须考虑将其分解为一个更优化的结构。然后,您会发现,在底层数据在24小时内保持不变的情况下,每天反复运行相同的查询是非常昂贵的,因此您转向了缓存设置。有许多运动部件,它可能会变得复杂,嗯,真的很乏味的快速。

当涉及到排行榜时,我是一个久经沙场的愤世嫉俗者,虽然它们对游戏机制和激励人很有帮助(每个人都喜欢看到分数!)做大规模的工作是件很痛苦的事情。

票数 12
EN

Stack Overflow用户

发布于 2010-01-03 04:16:32

您是否考虑过将这些统计信息保存在由观察者更新的单独的表/模型中?您在这里的视图中做了大量繁重的工作,这通常不是一个好的实践。

票数 3
EN

Stack Overflow用户

发布于 2011-06-17 14:53:52

我建议使用Redis。您可以运行cron类型的任务,从数据库中提取数据,然后将其放入Redis排序集中。排序集功能可能是存储排行榜的最好工具。http://redis.io/topics/data-types

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1992608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档