我有一个网站,使用多个MySQL查询计算用户参与/活动。
对于典型用户,我会问:
他们做了多少次更新? 他们上传了多少张照片? 等等。
这些只是相关表格,更新,照片的基本COUNT查询。然后我将每个的COUNT值相加得到一个分数。每个查询需要一个JOIN,每个查询大约需要0.0006秒,每个用户共有10个查询,总共0.006秒。
虽然对于一个用户来说并不是那么糟糕,但我必须为100,000个用户计算,理论处理时间为10分钟,并且有大约1,000,000个数据库查询。感觉我正以错误的方式接近问题并且想知道是否有人有任何想法?
我曾考虑将用户分数存储在他们的用户记录中,并在每次执行特定操作时将其递增但是它不那么灵活(我不能回去查看某一天累积了多少积分实例)。
任何帮助都非常感谢!
答案 0 :(得分:2)
拥有user_activity
链接表。它需要action_id
,user_id
和timestamp
。例如,当用户上传照片时,会创建一条记录activity_id
= 2(对于activities
表引用的“照片上传”),user_id
和当前时间戳。这很容易查询,并且当您拥有数以万计的用户时,无需担心长时间运行的查询。
答案 1 :(得分:2)
假设您的表格在每个表格都有某个user_id
字段的位置,您可以执行以下操作来获取用户完成的“活动”:
SELECT users.user_id,
(update_counts.update_count + photo_counts.photo_count) AS activity_count
FROM users
INNER JOIN
(
SELECT updates.user_id AS user_id,
COUNT(updates.*) AS update_count
FROM updates
GROUP BY user_id
) AS update_counts ON users.user_id = update_counts.user_id
INNER JOIN
(
SELECT photos.user_id AS user_id,
COUNT(photos.*) AS photo_count
FROM photos
GROUP BY user_id
) AS photo_counts ON users.user_id = photo_counts.user_id
GROUP BY users.user_id
显然你可以根据需要添加表格,你可以根据需要加权。如果你在每个表中的user_id
字段上有一个索引,它应该表现得相当好,尽管它取决于你的表有多大。
一旦表格变得庞大,您将需要开始在缓存表中缓存activity_count。如果需要,您可以按日期缓存值。
如果您只需要粗略估计,您可以按常规频率运行此查询(例如,每晚一次)并缓存结果;这比为每个表编写触发器以更新缓存表更具侵入性。
答案 2 :(得分:0)
除非你想进行11路连接,否则我会为每个用户更新后插入的目的创建一个单独的表。
该表应该只包含用户名,时间戳,部分(来自其中的表)以及其他表中的唯一ID,因此您可以对删除等进行反向引用。
答案 3 :(得分:0)
听起来好像你在真正需要之前尝试进行优化。如果您没有100,000个用户,则在必要时无需担心此类问题。
据说没有理由不优化,只是不要试图为你不需要的解决方案来解决问题。
虽然您可能会遇到轻微的不一致,但您可以尝试在登录时缓存每个用户计数的结果(使用memcached),并在更新其中一个计数时仅更新缓存。如果用户非常活跃,那么每小时左右更新一次会更有效。
答案 4 :(得分:0)
这可能对您的应用程序来说太过分了,但您可以随时使用OLAP路由。这将允许您沿多个维度(例如用户和时间跨度)预先聚合度量。这为您提供了一个灵活的框架,可满足各种报告需求。 SQL Server Analysis Services包对我们公司运作良好。