【问题标题】:Designing a scalable points leaderboard system using SQL Server使用 SQL Server 设计可扩展的积分排行榜系统
【发布时间】:2011-03-18 02:02:35
【问题描述】:

我正在寻找有关扩展积分排行榜系统的建议。我已经有了一个使用非常规范化策略的工作版本。第一个版本本质上是一个看起来像这样的表格。

UserPoints - PK: (UserId,Date) +------------+--------+----------+ |用户名 |积分 |日期 | +------------+--------+----------+ | 1 | 10 | 2011-03-17 07:16:36 | | 2 | 35 | 2011-03-17 08:09:26 | | 3 | 40 | 2011-03-17 08:05:36 | | 1 | 65 | 2011-03-17 09:01:37 | | 2 | 16 | 2011-03-17 10:12:35 | | 3 | 64 | 2011-03-17 12:51:33 | | 1 | 300 | 2011-03-17 12:19:21 | | 2 | 1200 | 2011-03-17 13:24:13 | | 3 | 510 | 2011-03-17 17:29:32 | +------------+--------+----------+

然后我有一个存储过程,它基本上执行 GroupBy 用户 ID 并对点求和。我还可以传递@StartDate 和@EndDate 参数来创建特定时间段的排行榜。例如,顶级用户的天/周/月/生命周期的时间窗口。

这似乎适用于中等数量的数据,但随着点记录的数量超过一百万左右,事情变得明显变慢。我正在使用的测试数据是由大约 500 名用户在 3 个月的时间跨度内创建的超过一百万个点记录。

有没有不同的方法来解决这个问题?我已经尝试通过将点预先分组到小时日期时间存储桶中来对数据进行非规范化,以减少行数。但我开始认为我需要担心的真正问题是需要在排行榜中考虑的用户数量不断增加。时间窗口大小通常会很小,但越来越多的用户将开始在任何给定窗口内生成点。

很遗憾,我无法访问“作业”,因为我使用的是 SQL Azure 并且代理不可用(还)。但是,如果您有足够的说服力,我对使用不同的存储系统进行扩展的想法持开放态度。

我过去的工作经验告诉我应该研究数据仓库,因为这几乎是一个报告问题。但同时我需要它尽可能实时。

更新

最终,我希望支持每周一上午 8 点到周五下午 6 点的自定义排行榜。但这是在路上,为什么我尽量不要太看中聚合。我现在愿意接受基本的日/周/月/年/所有时间窗口。

棘手的部分是我真的不能将它们非规范化存储,因为我需要这些窗口是 TimeZone 可转换的。该系统是多租户的,因此所有数据都存储为 UTC。问题是对于不同的客户,一周从不同的时间开始。将总和汇总在一起会导致某些点落入错误的存储桶中。

【问题讨论】:

    标签: sql database database-design azure azure-sql-database


    【解决方案1】:

    这里有一些想法:

    1. 坚持使用 SQL Azure:您可以拥有另一个表 PointsTotals。每次向 UserPoints 表添加一行时,还要增加 PointsTotals 中给定 UserId 的 TotalPoints 值(如果没有要增加的行,则插入新行)。现在,您始终可以为每个 UserId 计算总计。
    2. 使用 Azure 表存储:创建一个 UserPoints 表,分区键为 userId。这将所有用户的积分行保持在一起,您可以轻松地将它们相加。而且...您可以借鉴建议 #1 的想法,创建一个单独的 PointsTotals 表,其中 PartitionKey 是 UserId,RowKey 可能是总点数。

    【讨论】:

    • 我实际上已经有一个“PointsTotal”,但这不是问题。我需要能够为任何时间段创建用户排行榜。 (2 月 1 日 - 2 月 28 日)在尝试为特定日期范围内 500 多个用户订购积分时,表格存储无法正常工作。
    • 它真的必须适用于任何日期范围,还是仅适用于某天/某月/某周?即在 2 月 3 日至 4 月 6 日期间运行的查询是否需要快速运行?
    • 好的,还有一个问题,您需要能够在不同的客户中运行它们吗?
    【解决方案2】:

    如果是我的问题,我会忽略时间戳并按天存储用户和积分总数

    【讨论】:

      【解决方案3】:

      我决定采用存储点以及时间跨度(StartDate 和 EndDate 列)本地化到客户当前 TimeZone 设置的想法。我意识到这样做的一个额外好处是,我可以在几个 monts 之后“清除”旧的排行榜回合数据,而不会影响终生总积分。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-22
        • 2021-10-07
        • 2023-03-30
        • 2012-07-26
        • 2013-12-03
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多