在数据库级别跟踪计数器的最佳方法

时间:2017-12-14 09:41:23

标签: mysql sql sqlalchemy

我希望通过时间跟踪用户计数器,并能够随时间生成有关计数器中更改的统计信息。

关于这两个主要表格,我已经很好地设置了(尽管它们是我希望听到的更好的方式)。 user和counter_change看起来非常像这样:

user:
+-----------+------------+
| id        | username   |
+-----------+------------+
| 1         | foo        |
| 2         | bar        |
+-----------+------------+
counter_change:
+-----------+--------------------+------------+
| user_id   | counter_change_val | epoch_time |
+-----------+--------------------+------------+
| 1         | 10                 | 1513242884 |
| 1         | -1                 | 1513242889 |
+-----------+--------------------+------------+

我希望能够在前端显示当前计数器值(基值为0)以及一些统计数据(例如:昨天你的网络计数器是+10或者-2等)

我已经考虑了一些可能的解决方案,但它们似乎都不是完美的解决方案。

将计数器添加到user表(或在一些新的counters表上):

此解决方案似乎是更有效的资源,在插入counter_change时,使用counter_change_val更新user中的计数器。

优点:

获取计数器当前值几乎不会消耗任何资源。

缺点:

如果发生错误,counter_changes_val的总和可能与user中的计数器不同。

无法真正用于统计信息字段,因为它需要额外的查询,此时触发器会更方便。

在插入/更新时向user表(或某些新的counters表)添加计算的计数器:

此解决方案将包含一个SQL触发器或ORM级别的某种函数,它将使用counter_change_val的总和将插入值更新到counter_change表。

这也将用于暗示按日期分组的计算字段。例如,获取过去30天的平均每日更改。

优点:

获取计数器当前值几乎不会消耗任何资源。

缺点:

在每个插入中,都需要所有当前用户counter_change的聚合。

添加视图或使用计数器总和

进行选择

此解决方案包括创建视图或选择在需要时获取聚合counter_change_val的总和。

优点:

不向表格添加任何字段。

缺点:

在运行时计算它会增加请求响应时间的时间。 每次查询计数器时,都需要聚合counter_change值。

1 个答案:

答案 0 :(得分:0)

实际上,我不确定我是否明白你要做什么。不过,我建议选项1或选项2:

选项1是有效的,如果做得对,它足以安全地防止错误。例如,您可以在事务中包装插入counter_change并计算新的counter_value;这样可以防止任何不一致。您可以在后端软件或触发器中执行此操作(例如,在插入counter_change时)。

关于选项2,我不清楚为什么需要对当前用户的所有counter_change进行聚合。您可以在插入触发器中调整用户表中的counter_value,如同选项1一样,您可以使用事务来使其安全。

恕我直言,每次插入counter_change时调整当前的counter_value是最有效的解决方案。您可以在后端软件中或在触发器内执行此操作。在这两种情况下,都要使用交易。

选项3)不应该被使用,因为它会给系统带来很大的负担(假设每个用户有1000个counter_changes ......)。

关于统计数据:这与首先存储数据的问题不同。您可能需要对任何统计数据进行某种聚合。为了加快速度,你可以考虑缓存结果等等。