使用SQL Server设计可伸缩的点排行榜系统

时间:2011-03-18 02:02:36

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

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

UserPoints - PK: (UserId,Date)
+------------+--------+---------------------+  
| UserId     | Points | 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 UserID和Sums the Points。我还可以传递@StartDate和@EndDate参数来创建特定时间段的排行榜。例如,最佳用户的时间窗口为日/周/月/生命周期。

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

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

不幸的是,由于我使用的是SQL Azure,因此无法访问“作业”,但尚未提供代理。但是,如果您足够令人信服,我愿意使用不同的存储系统来扩展它。

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

更新

最终,我想支持每周星期一上午8点到周五下午6点的自定义排行榜。但那是在路上以及我为什么不想对聚合过于花哨。我现在愿意和基本的Day / Week / Month / Year / AllTime窗口达成和解。

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

3 个答案:

答案 0 :(得分:3)

这里有一些想法:

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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