我有一个系统显示按三个字段之一排序的条目,最受欢迎的今天,本周和本月。每次查看条目时,分数将增加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
所以在1日凌晨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吗?
非常感谢!
答案 0 :(得分:6)
这实际上是如何有效地分组数据并保留所有必要信息的常见问题。
首先:你尝试过自己的方式吗?你真的缺少存储吗?你的解决方案似乎很合理。
我假设您使用数据库来保存数据。
我会创建两个单独的表,一个用于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)天的每个条目都应删除。或者,如果您想要总计或年度统计数据
<强>优点强>
<强>缺点强>
答案 1 :(得分:2)
一个简单的解决方案是
Use an array of 31.
Today - the last value
This Week score would be the sum of the last 7 values.
This Month would be the sum of the last 31 values.
At the end of each day, shift the whole array values by 1 to accommodate new value.
关于你的评论,
Use another array of size 24 to store hours visit count.
Today - Sum of all elements of Array2
This Week score would be the sum of the last 7 values of Array1.
This Month would be the Sum of all elements of Array1.
At the end of each day, shift the whole array values of Array1 by 1
to accommodate new value. Last day visit count = Sum of all elements of Array2
答案 2 :(得分:2)
也许某种衰减可能会有所帮助。 Today
,Yesterday
,ThisWeek
,LastWeek
,ThisMonth
,LastMonth
需要6个变量。
然后,最终评级(例如每日)可以被计算为:Today + Yesterday * attenuation( current_time - start_of_the_day )
。
衰减类似于1 / (1 + k * time)
,其中k
可以调整,具体取决于您希望最后一天的评分缩短的速度。
更新:考虑在一天内查看123次新条目。让我们以秒为单位测量时间,以获得一些数字。在23:59,etrys的评分为123 + 0 * 1 / (1 + k * 86340)^2 = 100
。
午夜Today
计数器变为Yesterday
:
0 + 123 * 1 / ( 1 + k * 0)^2 = 123
假设在中午之前,一个条目可以获得89个以上的观看次数。
89 + 123 * 1 / ( 1 + k * 43200 )^2 = ?
嗯,现在是选择k
的好时机。如果我们希望旧视图在12小时内淡出四次,则k
将为1/43200
。如果我们想要衰落一百次 - 9/43200
。在这种情况下:
89 + 123 * 1 / ( 1 + 9 )^2 = 90.23
然后到23:59。让条目获得60多个视图
149 + 123 * 1 / ( 1 + (9/43200) * 86340 )^2 ~= 149.002
所以昨天的观点几乎完全失去了对24小时评级的影响。当然,您可以使用k
或衰减公式,以最好地满足您的需求。这只是一个例子。