首页 > 解决方案 > 数据库太大 - 存储为一行或序列化数据?

问题描述

我有构成许多包含问题的模块的测验应用程序。每个问题都有许多类别(多对多)。每次完成测验时,用户的分数都会发送到分数表。(为了澄清目的,我附上了一个实体关系图)。

我一直在考虑根据类别分解用户分数(即用户在完成测验时将获得总体测验分数以及每个类别的分数)。

但是,如果每个测验至少包含 30 个问题,那么每个测验可能有大约 15-20 个类别。因此,如果一个用户完成了一个测验,那么它将在分数表中创建至少 15-20 行。如果有多个用户,Scores 表会很快变得非常大。

我认为这会影响从分数表中检索数据的性能。例如,如果我想计算特定类别的用户的平均分数。

有没有人对我如何仍然能够根据类别存储分数有更好的建议?

我考虑过序列化 JSON 数据,但当然,这有其局限性。

数据库 ERD

标签: mysqldatabaselaravelperformanceeloquent

解决方案


数据库应该能够处理数百万行,并且您的设计本身没有任何问题。我建议的几件事:

  • 将索引放在以下(或组合)用户 id、考试 id(我假设你称之为 scorable id)考试类型(scorable Type?)和创建日期中。

  • 随着表的增长,对它进行分区。潜在的候选人可能是创建日期桶(按年或年/月可能会很好),或者如果学生在特定的班级,你可以有班级桶

  • 随着您的表增长得更多,您可以将分区移动到不同的不同磁盘(如何对数据进行分区在这里将更加重要,因为如果数据必须跨越太多分区,您最终可能会损害性能而不是帮助)

除此之外,另一个建议是将分数表分成两个 score 和 scoreDetail。分数表将包含顶级内容,如用户 ID、考试 ID、总分等......而子表将包含按类别(哲学等......)的分数。我敢打赌,80% 的时间人们只关心最高分。这样,只有当有人想在特定考试中获取他们的分数详细信息时,您才可以使用更大的表格。

最后,您可能希望按行而不是列按类别得分,以便更轻松地进行分析和聚合,但这不一定是性能提升器,实际上取决于您计划如何使用数据。

最后,最好的优化实际上取决于您计划如何使用您的数据。我建议只创建一个代表几年数据的随机数据集并使用它。


推荐阅读