【问题标题】:Database design for awards system - Count on the fly or use separate/join table?奖励系统的数据库设计 - 即时计数或使用单独/连接表?
【发布时间】:2014-02-07 00:07:22
【问题描述】:

可以将以下场景与 StackExchange 信誉系统进行比较。我想知道在性能和可扩展性方面哪种方法最好。

场景:我有一个游戏网站,我需要为用户颁发奖牌奖励。每枚奖牌显然都有自己的要求。示例:参加一定数量的比赛;连胜;一场比赛的前1名;等等

选项 1:如果在注册新匹配时满足条件,则将记录存储在连接表 (users_medals) 上。一开始这会更简单、更快,但很难跟踪未来条件的变化(例如:增加某些奖牌所需的胜利次数)。

选项 2:每次用户浏览用户个人资料时,不要存储任何关系并执行所有计算。它可以轻松处理条件的变化,但是用户和奖牌越多,显示用户信息的速度就越慢,更糟糕的是,显示用户列表。

【问题讨论】:

  • 选项3:运行计划任务以检测新奖牌并保留结果。
  • 关于选项 2 - 在不断变化的条件下,你真的会拿走来之不易的奖牌吗?
  • 嗯,是的,在某些情况下我必须这样做。改变标准的一个常见原因是平衡事情。如果老用户有更多的勋章,那对新用户是不公平的,因为在新用户加入之前要求更容易。但是,是的,它至少应该可以选择保留旧奖项。
  • @MitchWheat 你能详细说明一下吗?这种方法在类似的系统(例如 stackoverflow)上更常见吗?与选项 1 相比,我在那里看到的一个优势是,我可以更好地控制标准的更改(以及随之而来的获得奖牌的更改)何时生效。但我仍然希望用户在比赛结果发布后立即看到他们的收入。我想在这种情况下,我应该在比赛后正常检测和存储奖励,并让计划任务稍后在适用时更正它们(标准已更改)。

标签: database-design scalability database-performance


【解决方案1】:

首先,我同意 miraculixx 的观点,已经获得的奖牌应该留在用户手中。因此,您应该将获得的奖牌与用户记录一起保存在一个联合表中,或者使用我用来显着加速应用程序的方法:

  1. 有一个表格存储奖牌名称 + 达到它的标准
  2. 将获得的奖牌的 ID 存储在用户记录的列中(逗号分隔、Json、Hstore、XML...) - 这有点非规范化,但会显着提高查找速度。
  3. 可能会添加另一个表格,每项赛事都会获得新奖牌,因为您可能希望让用户可以选择查看他们的历史记录、比较人们实现目标的速度等等。

我绝对不会选择您的路线 2,因为随着用户群的增加,您会遇到非常糟糕的性能问题。

现在,当用户查看他们的个人资料时,您的应用将遍历带有奖牌 ID 的列,然后将它们从您的小桌子上拉出,可能有几十个不同的奖牌并显示(毫秒),而不是计算哪些奖牌他赚了(在大桌子上很慢)。你的用户可以拉历史记录,你可以创建统计等等。

如果您更改标准以达到某些目标,使用以前标准达到的现有用户保留他们的奖牌,新用户需要满足新标准。如果您不希望这样,请拿走获得的奖牌(人们会非常生气;-))

【讨论】:

    【解决方案2】:

    恕我直言,提供可扩展但快速的解决方案的最佳方法是缓存计算值。我会将东西分解成多个表(或在任何 nosql db 中调用的任何表),但计算更改并将它们持久化 - 快速很重要。唯一与用户相关的缺点是包含在术语eventual consistency 中的某些不一致。取决于你的用户会容忍什么。

    我认为如何思考此类问题和解决方案的最佳示例是研究某人将如何使用 redis 设计 twitter 解决方案,请参阅http://redis.io/topics/twitter-clone

    【讨论】:

      猜你喜欢
      • 2015-07-02
      • 2011-07-01
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多