在数据库中设计“总计”字段

3

我正在寻找一个最优的解决方案来处理我的数据库(MySQL),但是我卡在了一个决定上,即是否存储一个Total列。

这是我的数据库的简化版本:

我有一个Team表,一个Game表和一个'Score'表。 Game将有{teamId,scoreId,...},而Score表将有{scoreId,Score,...}(这里的...表示表中的其他列)。

在主页上,我需要显示团队及其得分的列表。随着时间的推移,团队的数量将增长到数百个,而得分列表将增长到数万个。哪种方式更好:

  • 每次请求页面时,我应该总结得分并显示在团队旁边。(我不想缓存,因为得分会不断变化)还是
  • 我应该在Team表中有一个total_score字段,在为该组添加新得分时更新该团队的总得分?

这两种方法哪种更好,或者是否有其他更好的方法?


4
除非确实必须这样做,否则不要在事务性数据库中存储计算出来的值。 - cadrell0
好的。我只是想了解一下:你能否举个例子,让我明白在哪种情况下我“绝对必须”这样做? - TJ-
3
@TJ-,如果查询性能至关重要,例如。 - Sergio Tulentsev
我会加入cadrell0的建议:不要存储计算出来的值。根据你的硬件和表格大小,如果性能开始变差,你仍然可以决定以后去规范化。但是根据你提供的数据量和适当的索引,我真的不认为这应该是一个问题。 - iDevlop
4个回答

2

在决定存储计算值时,我使用两个准则。在最理想的情况下,以下两个陈述都是正确的:

1)该值必须具有高昂的计算成本。
2)该值的改变概率必须很低。

如果计算值的成本非常高,但它每天都会更改,那么我可能会考虑创建一个每晚更新该值的作业。

开始时不加总列,只有在出现性能问题时才添加。


我想我会选择总列。不过还是谢谢你的建议。 - TJ-

1

在请求时计算总和可以更准确,但效率较低。

将总数缓存到字段中(非常)提高了某些查询的性能,但增加了代码复杂性或可能显示过期数据(如果您不是同时更新缓存值,而是通过cron作业更新)。

由您决定!:)


1

我认为在特殊情况下可以使用计算值,例如对数据库的月末快照。

我建议创建一个只包含一个列的 视图,该列等于你所需计算的总列。这样,你就可以查询视图而不是基本表。


0

根据您的分数更新频率和“分数”的确切含义而定

情况1:分数是实时得分

如果“分数”是实时得分,例如“板球或棒球中的得分”或“排球比赛或乒乓球比赛的得分”,那么我真的不明白为什么需要显示“运行”分数的“总和”。但是,在某些情况下,这也可能是要求,例如显示团队到目前为止得分的总和+正在进行(实时)游戏的得分。

在这种情况下,我建议您选择另一种选项,即结合您的第一和第二个选项

团队表中的Total_score将是很好的选择,并稍微更改您的数据模型。具体来说,可以在分数表中添加一个名为LIVE的新列,已完成的比赛为0,正在进行的比赛为1(可选地,表示比赛即将开始,但分数不会更新的-1)

现在联合两个表,类似于

select team_id,sum(total_sore) from (
select team_id,total_score from team
union
select team_id,sum(score) total_score from scores where live = 1 group by team_id)subquery
group by team_id

案例二:分数只是结果

好吧,直接查询数据库(您的第一选择)即可,因为结果只会在比赛结束后更新,并且实际上它将成为得分表中的新条目。

如果我的假设是正确的,那么得分只有在比赛结束后才会更新。此外,考虑到团队所玩的比赛,更新甚至可能更少。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接