存储/计算用户分数的最佳方式是啥?

Posted

技术标签:

【中文标题】存储/计算用户分数的最佳方式是啥?【英文标题】:What's the best way to store/calculate user scores?存储/计算用户分数的最佳方式是什么? 【发布时间】:2009-05-07 21:59:10 【问题描述】:

我正在为一个网站设计一个数据库,让用户能够通过执行某些活动获得积分(声誉),但我正在为数据库设计而苦苦挣扎。

我计划记录用户所做的事情,这样他们提交的物品可能会获得 25 分,他们制作 30 厘米每人获得 1 分,以及另外 10 分因为表现出色!

显然所有数据都将在那里,但似乎很多或查询以获得我想在他们的用户名旁边显示的每个用户的总分(以级别的形式)。例如,查询提交的项目表以从该用户那里获取每个项目的分数,查询 cmets 表等。如果所有这些都需要为页面上提到的每个用户完成......很多查询!

我曾考虑在用户表中保留一个分数,这样查找起来似乎要快得多,但我已经意识到存储可以从其他数据中计算出来的数据是 糟糕的!

我见过很多做类似事情的网站(甚至堆栈溢出也类似),所以我认为必须遵循“最佳实践”。谁能建议它可能是什么?

任何建议或 cmets 都会很棒。谢谢!

【问题讨论】:

【参考方案1】:

我认为这绝对是一个很好的问题。我必须构建具有与此类似行为的系统 - 特别是当经常访问其中包含分数的表时(就像在您的场景中一样)。这是我给你的建议:

首先,创建一些如下所示的表(我使用的是 SQL Server 最佳实践,但您可以随意命名它们):

UserAccount          UserAchievement
 -Guid (PK)           -Guid (PK)
 -FirstName           -UserAccountGuid (FK)
 -LastName            -Name
 -EmailAddress        -Score

完成此操作后,继续创建一个类似于以下内容的视图(不,我尚未验证此 SQL,但它应该是一个好的开始):

SELECT [UserAccount].[FirstName]      AS FirstName,
       [UserAccount].[LastName]       AS LastName,
       SUM([UserAchievement].[Score]) AS TotalPoints
FROM [UserAccount]
INNER JOIN [UserAchievement]
     ON [UserAccount].[Guid] = [UserAchievement].[UserAccountGuid]
GROUP BY [UserAccount].[FirstName],
         [UserAccount].[LastName]
ORDER BY [UserAccount].[LastName] ASC

我知道您提到了一些关于性能和大量查询的担忧,但是如果您构建这样的视图,您将永远不需要超过一个。我建议不要将其作为物化视图;相反,只需为您的表编制索引,以便您需要的查找(本质上是 UserAccountGuid)将启用整个表的快速求和。

我还要补充一点——如果您的 UserAccount 表变得很大,您可以考虑使用更智能的查询,该查询将包含您需要汇总的帐户名称。当您只在页面上显示 3-10 个用户的信息时,这将使您不会将大量数据集返回到您的网站。我必须多考虑一下如何优雅地做到这一点,但我建议远离“IN”语句,因为这会调用表的线性搜索。

【讨论】:

【参考方案2】:

对于非常高的读/写比率,非规范化是一个非常有效的选项。您可以使用索引视图,并且数据将以声明方式保持同步(因此您永远不必担心有坏分数数据)。缺点是它保持同步。所以对商店总数的更新是提交分数操作的同步方面。这通常会很快,但这是一个设计决定。如果您对自己进行非规范化,您可以选择是否需要某种延迟更新系统。

我个人会从索引视图开始,然后如果您需要的话,您可以用一个具体的表格相当无缝地替换它。

【讨论】:

对不起,我很笨 - 没有注意到 mysql 方面。我认为这还没有索引视图。强制它保持同步的正常替代方法是设置触发器。【参考方案3】:

过去,我们总是使用某种夜间或定期 cron 作业来计算当前分数并将其保存在数据库中 - 有点像活动表上 SUM 的持久视图。像大多数“最佳实践”一样,它们只是指导方针,在非常特定的领域偏离特定的硬性实践通常会更好、更实用。

另外,如果您使用 cron 作业,这实际上并没有太大的偏差,因为它最好被视为存储在数据库中的缓存。

【讨论】:

【参考方案4】:

如果您有一个单独的分数表,您可以在每次提交项目或用户发表评论时更新它。您可以使用触发器或在站点代码中执行此操作。

用户分数会不断更新,可以快速查询显示。

【讨论】:

以上是关于存储/计算用户分数的最佳方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

存储最后 3 个分数并删除旧分数并计算平均值?

这些 F 分数是啥意思?使用 SelectKBest 功能

计算在 Google App Engine 数据存储区中计算分数和日期的索引

Excel中表示计算结果为 FALSE 是啥意思

GridSearchCV 是不是存储所有参数组合的所有分数?

如何更有效地计算 n 个字符串之间的不匹配分数?