【问题标题】:noSQL/SQL/RoR: Trying to build scalable ratings table for the gamenoSQL/SQL/ERRoR:尝试为游戏构建可扩展的评分表
【发布时间】:2010-03-26 02:19:07
【问题描述】:

我正在尝试解决复杂的事情(在我看来)。

我有下一个实体:

  1. PLAYER(很少,名字像“John”、“Peter”等)。每个都有唯一的 ID。为简单起见,我们认为这是他们的名字。

  2. GAME(其中很少有,例如命名为“捉迷藏”、“跳跃和奔跑”等)。相同 - 每个都有唯一的 ID。为简单起见,暂时将其命名。

  3. 分数(它是数字)。

那么,它是如何工作的。

每个玩家都可以玩多个游戏。他在每场比赛中都获得了一些分数。

我需要建立评级表——而不是一个!

表 #1:最常玩的游戏 表#2:所有比赛中最好的球员(比如每场比赛的总得分)。 表 #3:每场比赛的最佳球员(特别是那场比赛的得分)。

我可以立即构建一些东西,但这不会奏效。 我将拥有超过10,000名玩家;和 15 场比赛,肯定会增长。 游戏中玩家的得分可以低至 0,也可高达 1,000,000(目前不确定是否可能更高)。所以我真的需要一些相关的数据。

有什么建议吗?

我打算用 SQL 来做,但可能只是将它用于键值存储;任何东西——欢迎任何想法。

谢谢!

【问题讨论】:

    标签: sql nosql


    【解决方案1】:

    我想说两件事。

    首先我回答你的问题。其次,我认为你应该这样做。

    1.答案:

    SQL,很容易开发和测试+生产一段时间。 玩家表,具有 INT 或其他一些 uniq 值,而不是字符串。 (我知道你说它是一个样本,但是选择应该给你足够的唯一 ID 的“长字”整数 游戏也是如此。现在,保持高分的关键是在两者之间建立关系。

    分数(表关系):

    [Player ID][Game_ID][Score]
    

    其中 score 是一个数值...我不知道你每场比赛的最高分,所以你弄清楚什么类型就足够了。

    现在,这应该很容易实现。让它发挥作用。但不要每次都直接调用数据库。

    构建 3 层架构。制作一个数据层和一个业务层,然后是“游戏”层。 因此,每个游戏都使用自己的“游戏 ID”调用业务层,例如:

    PlayerSaveScore(int gameID, int playerID, int score)
    

    然后,Businesslayer 会检查“参数”的大小是否正确并且是有效的 ID,也许会验证该玩家实际在过去 5 分钟内一直在会话中等等。

    验证后,业务层调用数据层以获取“更新表”,如果记录存在,数据层首先查看该数据层。如果不是,则将其插入。

    分层设计 一旦您“在线”(在空中)并且游戏变得流行,那么您就可以开始“升级”,但您仍然可以使用“未来可扩展的解决方案”继续前进。请记住,每个游戏都必须调用业务对象/层,而不是直接调用 - 绝不!

    我一直处于同样的“想了很多次”,但我一直进入一个称为准备的简单循环,但这几乎从未让我进入一个快速启动并运行的现实解决方案。

    所以首先获得100000名玩家!然后当它超出时开始担心。

    2。部分...如何扩展...建议:

    这就是我构建“businesslayer/webservices”的所有麻烦的原因...... 最重要的是,您的速度问题现在可以很好地解决。

    你可以很简单地实现“缓存”。

    你做一个额外的桌子,如果你只有 15 场比赛,你不需要桌子公关。游戏,但你决定。那个只保留每场比赛的前100名。每次您发布玩家的新记录时,您都会在此“前 100 名”中进行选择,并检查发布的值是否进入列表。如果是这样,则通过更新前 100 名表来处理它,以提高速度。

    将 Top 100 的摘录构建为静态数据列表,例如。 XML 或类似的静态数据。根据您的平台,您可以为自己选择正确的“静态格式”。

    您甚至可以进一步提高速度。只需保持获得每场比赛前 100 名所需的最小值即可。那将是一个创纪录的公关。游戏。

    然后将玩家得分与游戏的“前 100 名中的最低得分”进行匹配......如果高于,那么你需要做一些“缓存/索引”,然后你称之为“巨型排序”:o)

    明白了吗?我知道这是一个很长的答案,但我想向您发布一个“完整”的解决方案。

    希望您将此标记为您的答案 :o)

    【讨论】:

    • 好吧,谢谢,但是(总是有“但是”,不是吗?): 1. 我不想那样构建。我不担心成长。这是我的要求。我知道会发生什么,并且有我的理由。所以我只需要把它当作给定的;不是因为我确定我是那些一夜之间变得如此受欢迎的“特别”者之一——但这只是它需要做的方式,并且有客观的要求,讨论哪些真的超出了我的问题。对不起。 2.您的解决方案中没有任何类型的调整:经常和多次写入;改变每个球员的位置。不幸的是;-(
    • @alexeypro - 当有人给你写了这么长的答案,非常详细,有趣和正确,即使你不想使用它,请至少给它一个大拇指! :-)
    • @alexeypro,你能解释一下你在我没有回答的原始问题中问了什么吗?当我阅读您的评论时,您有新问题并扩展了问题?还是我错了?
    【解决方案2】:

    我不明白为什么不能用一个分数表和简单的 SQL 查询来解决这个问题:

    (未经测试的伪 SQL)

    create table scores {
      player_id as integer,
      game_id as integer,
      score as integer
    }
    

    最常玩的游戏:SELECT count(*) AS c FROM scores GROUP BY game_id ORDER BY c DESC

    最佳球员:SELECT sum(score) AS s FROM scores GROUP BY player_id ORDER BY s DESC

    给定游戏中的最佳玩家:SELECT * FROM scores WHERE score=(SELECT max(score) FROM scores WHERE game_id=$given_game) LIMIT 1

    如果您需要同时获得所有游戏中最佳玩家的列表,您可以稍微扩展最后一个查询(这可能可以通过连接进行优化,但我现在考虑还为时过早) .

    您所说的行数在数据库方面很少。如果您也缓存查询结果(例如,通过 memcached 之类的东西,或在您的 RoR 应用程序中),那么您几乎不会为此接触数据库。

    【讨论】:

      猜你喜欢
      • 2011-06-20
      • 2021-09-16
      • 2012-12-16
      • 2021-03-20
      • 2016-01-16
      • 2011-04-17
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多