Sql 什么';存储/计算用户分数的最佳方法是什么?

Sql 什么';存储/计算用户分数的最佳方法是什么?,sql,mysql,database,database-design,Sql,Mysql,Database,Database Design,我期待着为一个网站设计一个数据库,用户将能够获得执行某些活动的积分(声誉),并与数据库设计挣扎 我计划记录用户所做的事情,这样一来,他们提交的一个项目可以得到25分,30条评论每人得1分,另外10分奖励他们的出色表现 很明显,所有的数据都会在那里,但要获得每个用户的总分似乎需要很多或查询,我想在他们的用户名旁边显示这些总分(以级别的形式)。例如,查询提交的项目表以从该用户处获取每个项目的分数,查询评论表等。如果需要为页面上提到的每个用户执行所有这些操作。。。。很多疑问 我曾考虑过在用户表中保留一

我期待着为一个网站设计一个数据库,用户将能够获得执行某些活动的积分(声誉),并与数据库设计挣扎

我计划记录用户所做的事情,这样一来,他们提交的一个项目可以得到25分,30条评论每人得1分,另外10分奖励他们的出色表现

很明显,所有的数据都会在那里,但要获得每个用户的总分似乎需要很多或查询,我想在他们的用户名旁边显示这些总分(以级别的形式)。例如,查询提交的项目表以从该用户处获取每个项目的分数,查询评论表等。如果需要为页面上提到的每个用户执行所有这些操作。。。。很多疑问

我曾考虑过在用户表中保留一个分数,这样看起来查找起来会快得多,但我一直认为存储可以从其他数据计算的数据是不好的

我见过很多网站做类似的事情(甚至堆栈溢出也做类似的事情),所以我想一定有一个“最佳实践”可以遵循。有人能告诉我可能是什么吗


任何建议或意见都会很好。谢谢

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


就我个人而言,我会选择索引视图作为开始,然后,如果需要的话,您可以用一个具体的表来无缝地替换它。

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


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

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


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

我认为这绝对是一个很好的问题。我必须构建具有类似行为的系统——特别是经常访问包含分数的表时(如您的场景中)。以下是我给你的建议:

首先,创建一些表,如下所示(我使用的是SQL Server最佳实践,但按照您认为合适的方式命名):

完成此操作后,继续创建一个类似以下内容的视图(不,我还没有验证此SQL,但这应该是一个良好的开端):

我知道您提到了一些关于性能的问题和很多查询,但是如果您构建这样一个视图,您将永远不需要超过一个。我建议不要将此视为具体化视图;相反,只需为表编制索引,以便所需的查找(本质上是UserAccountGuid)能够在整个表中实现快速求和


我将再添加一点——如果您的USER帐户表变得庞大,您可以考虑一个稍微智能的查询,该查询将包含需要卷起的帐户的名称。这样,当你只在网页上显示3-10个用户的信息时,就可以不将大量数据集返回到你的网站。我必须多想一想如何优雅地做到这一点,但我建议不要使用“IN”语句,因为这将调用表的线性搜索。

对不起,我很笨-没有注意到mysql方面。我认为还没有索引视图。强制它保持同步的正常替代方法是设置触发器。
UserAccount          UserAchievement
 -Guid (PK)           -Guid (PK)
 -FirstName           -UserAccountGuid (FK)
 -LastName            -Name
 -EmailAddress        -Score
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