3

I have an application where users's activity will be rewarded with points. There will be a points chart that will assign a certain amount of points for certain action.

My question is which approach is better and most importantly why?

Approach 1: - create a userPoints table in mysql and insert points there at each user action. When the user goes to their profile, query the database for the number of points and display them.

example:
user buys an item
query the database: insert 5 points in userPoints for user 2
user follows a place
query the database: insert 7 points in userPoints for user 2
user sells their item
query the database insert -5points in userPoints for user 2

Approach 2: - do not store the points in a table, but count the number of actions user has completed (get their count and type from the db) and then multiply by the certain amount of points for each type of action all at runtime, whenever number of points is required (for example when they visit their profile)

example:
user visits their profile to see how many points they have
query the database and count items possessed, places followed, friendships and then multiply items count x5, followings count x7 and friendships count x10 and display the number

EDIT for Steven:

let me get this straight, is this the chronology of actions I am supposed to take? How can I tighten this up and reduce the number of queries?

  • buying an item has an actionId of 1 and points rewarded are 5 (this is specified in the - actions table in the db)
  • Kylie (user ID: 1) buys an item.
  • Query DB: Add the item to userItems table for user ID1
  • Query DB: Register an action in the userActions table - userId: 1, actionId: 1
  • Query DB SET userPointsTotal = userPointsTotal + points rewarded (nest two queries in one like this: set userPointsTotal = userPointsTotal + (select points from actions where actuionid= 1))
  • Query DB get userPointsTotal and display value at Kylie's profile
  • In the future, refer table userActions so user can get status title, depending on certain type of activity (social status or possessions status)
4

3 回答 3

1

我推荐一种混合方法。如果你在表中严格存储积分,很容易忘记谁有哪些积分,因为什么原因。或者,如果您的用户群增长,不断地重新计算它们会立即关闭您的服务器。如果您改为每 5 分钟、1 小时、12 小时或任何适合您的时间间隔重新计算点数,并将结果存储在 userPoints 表中,您可以快速访问,因为您只是在查找表。此外,如果您碰巧计算错误或弄乱了用于计算点的逻辑,您可以轻松修复代码并重新计算。

于 2013-10-26T13:05:03.563 回答
1

由于可以将点数视为基于单个操作的聚合函数,因此问题归结为何时使用预聚合的决定。

这两种方法在不同的情况下都有效:

  • 当计算聚合需要很少的工作,或者不经常计算聚合时,使用预聚合会增加复杂性,甚至可能会降低性能,因此存储“原始事件”是更可取的。
  • 当计算聚合需要处理大量数据时,或者经常请求聚合时,预聚合成为提高性能的有效方式。

请注意,数据库可以帮助您进行预聚合:如果您在操作表上定义索引,然后查询计数和总数而不是单个操作(即按照您在问题方法 2 中建议的方式进行操作),那么数据库将使用索引中的数据来获取计数,而无需实际进行计数。这为您提供类似于第一种方法的性能,RDBMS 为您完成大部分工作。

于 2013-10-26T13:07:36.600 回答
1

您将要存储:

  1. 动作- 列出动作和为每个动作定义的点的表格。这将充当您的域表。

  2. 用户操作- 一个复合键表 (user_id, action_id) 列出用户完成的操作和他们获得的积分(您需要将其存储在这里,以防用户完成后操作的积分值发生变化。随时您可以通过 SUM(user_actions.points) 获得用户获得的准确总积分。

  3. 用户总数- 枚举用户获得的总积分的值。您可以在记录用户操作时更新用户表上的列,或者这可以是存储在用户索引或缓存中定期更新的某个地方的 user_actions.points 的总和(例如 Solr、Memcached)。这将允许您在每次显示用户列表时显示大量聚合数据,而无需使用昂贵的聚合函数来冲击您的数据库。

这为您提供了世界上最好的。您有一个快速的方法来说明用户获得了多少积分,如果他们“偏离”了重新计算总数的可靠方法,以及参考完整性/附加信息的域表。

于 2013-10-26T13:18:57.487 回答