一尘不染

今天流行,本周,本月-设计模式

algorithm

我有一个系统,该系统显示按以下三个字段之一排序的条目:最受欢迎的“今天”,“本周”和“本月”。每次查看条目时,分数就会增加1,从而改变顺序。

因此,如果条目1是新条目并且今天被查看了10次,则其得分将为:

Today: 10
Week: 10
Month: 10

当前解决方案

目前,我仅将3个字段与每个条目相关联,一个字段用于今天,另一字段用于本周,另一个字段用于本月。每次查看条目时,所有三个分数都会加1。

在一天结束时,天分数将重置为0。在当前星期末,周分数将设置为0,在当前日历月末,月分数将设置为0。

问题

尽管这种方法有效且占用空间很小,但由于以下两个原因,它并不理想:

1)在当前时间段(天,周,月)结束时,该值立即全部重置为0,这意味着在每天的00:00:00排名全部重置并且所有每日得分均设置为0,周末和月底也是如此。在每个月1号的00:00:00,所有得分都设置为0,从而丢失了所有现有排名数据。

2)由于月末通常在一周内(周一至周日),因此每月得分将在一周内重置,导致每周得分高于每月得分。

可能的解决方案

我可以在每月的每个小时使用滚动小时计数器,该计数器用于根据当前小时指数计算当日,周,月的分数。

Array size = 31 * 24 = 744 int16 values

因此,第一天凌晨4点,视图将被放置在几小时内[4]

hours[4]++

然后,统计信息计算器将今天用作最后24个值的总和,而“本周”得分将是最近(24 * 7)个值的总和。最后,本月将是最后(24 * 31)个值的总和。

解决问题

解决方案1的主要问题是磁盘/内存要求。我从在当前解决方案中使用3个32位值转变为使用744个32位值。即使我将它们更改为in16,每个条目仍将使用更多内存

Memory per Entry = 3 * 4 bytes = 12 bytes (Existing)
Memory per Entry = 744 * 2 = 1,488 bytes (possible solution)

通过此解决方案,我每个条目的内存使用量已跃升了12400%!

谁能提出另一个解决方案,该解决方案可以解决我当前解决方案中的问题,但每个条目不使用1.5k?

非常感谢!


阅读 217

收藏
2020-07-28

共1个答案

一尘不染

这实际上是一个常见的问题,即如何有效地对数据进行分组并保留所有必要的信息。

首先:您是否尝试过自己的方式?您真的缺乏存储空间吗?您的解决方案似乎很合理。

我会怎么做

我假设您正在使用数据库来保存数据。

我将创建两个单独的表,hourly一个用于daily统计,一个用于统计。每篇文章在该数据库中将有24行,每小时一行。这将用于hourly统计数据。要更新特定行,您只需知道小时(0-23)和entry_id。UPDATE count=count+1 WHERE hour=11 AND entry_id = 18164;

entry_id foreign key | hour integer | count integer
---------------------+--------------+--------------
1                    | 0            | 123
1                    | 2            | 1712
...

当前的每日统计信息将在午夜左右(或在应用执行最少操作时)进行计算或按需求和。无论哪种方式,每天都必须对所有小时数据进行汇总,并且必须将其插入daily统计表中。

entry_id foreign key | day date   | count integer
---------------------+------------+--------------
1                    | 2013-07-03 | 54197
1                    | 2013-07-04 | 66123
...

超过31(30/29/28)天的每个条目都应删除。是否需要总统计或年度统计

优点

  • 您保留的数据少于完整的每小时统计数据:24 + 31
  • 如果在entry_id和hour上建立索引,则小时表上的总和应该很快
  • 比解决方案中使用的内存更少

缺点

  • 每日更新统计信息所需的其他脚本/触发器/作业
  • 实施它比解决方案需要更多的工作
2020-07-28