PHP/MySQL - 记录用户活动和大量数据库负载

8
假设我们需要记录社区中所有用户的活动,我想很快我们的数据库就会变得非常庞大; 所以我的问题是:
为了提供这种服务,这样做是否是可以接受的妥协(拥有一个巨大的DB表)?还是我们可以用更有效的方式来实现?
编辑: 要记录的活动类型是“经典”的社交网络活动日志,人们可以查看其他人正在做什么或已经做过的事情,反之亦然,因此它将跟踪例如用户何时编辑个人资料、发布内容、登录、注销等。
编辑2: 我的表已经针对仅存储id进行了优化。
log_activity_table(
id int
user int 
ip varchar
event varchar #event-name
time varchar
callbacks text #some-info-from-the-triggered-event
)

你打算如何使用日志数据以及使用频率是多少? - prodigitalson
@prodigitalson:它将用于另一个类似社交网络的系统中。因此,它看起来像经典的“约翰·多说”,评论,访问,添加,下载,发布等等...,所以我想它会经常出现。 - Julie Rokk
1
http://forums.mysql.com/read.php?153,268034,268061#msg-268061 - Calum
@Calum:谢谢你的链接!;) - Julie Rokk
没问题 :) 这个看起来不错!http://www.databaseanswers.org/data_models/social_networking/index.htm - Calum
@Calum,很遗憾第一个链接失效了。 - Omar Dulaimi
3个回答

8

我正在研究一个类似的系统,所以我对你得到的答案很感兴趣。

对于我的项目来说,完整的历史记录并不重要,因此我们选择保持表格相对简洁,就像你现在做的一样。我们的表格大致如下:

CREATE TABLE `activity_log_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `event` varchar(50) NOT NULL,
  `subject` text,
  `publisher_id` bigint(20) NOT NULL,
  `created_at` datetime NOT NULL,
  `expires_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `event_log_entry_action_idx` (`action`),
  KEY `event_log_entry_publisher_id_idx` (`publisher_id`),
  CONSTRAINT `event_log_entry_publisher_id_user_id` 
    FOREIGN KEY (`publisher_id`)  
    REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

我们决定不永久存储历史记录,因此我们将设置一个cron作业,在一定时间后删除历史记录。我们为了方便起见,同时拥有了created_atexpired_at列。当事件被记录时,这些列会自动由模型更新,并使用简单的strftime('%F %T', strtotime($expr)),其中$expr是我们从配置中提取的类似于'+30 days'的字符串。
我们的subject列类似于您的callback列。我们也选择不直接将活动主题与其他表相关联,因为可能并非所有事件主题都有相应的表格,此外,保持此关系甚至并不重要,因为我们对此事件日志所做的唯一事情就是显示活动消息。我们存储了一个与事件相关的序列化值对象,以供预先确定的消息模板使用。我们还直接编码了事件所涉及的内容(例如个人资料、评论、状态等)。
我们的events(也称为活动)是简单的字符串,如'update''create'等。这些用于某些查询,当然也有助于确定向用户显示哪条消息。
我们仍处于早期阶段,因此这可能会有很大变化(可能基于对这个问题的评论和答案),但考虑到我们的要求,这似乎是一个不错的方法。

是的,看起来我们在做同样的事情;)我的问题是:例如当有人编辑自己的个人资料并触发“保存更改”多次时,那么我们就会有一堆无用的数据库条目,在“登录”和“注销”时也会发生同样的事情,所以在这种情况下,我想我应该只是“更新”而不是“插入”,否则如果有人发布评论或新闻,我们将不断“插入”。你对此有什么看法?+1 - Julie Rokk
@Julie:实际上,我们上周五刚讨论过这个问题... 我们正在考虑将实体类型从“subject”值对象序列化(或复制)到它自己的列中,并添加一个更新时间列。这样,如果给定事件的“subject”和“updated_at”列在一定时间段内(比如12-24小时)内,则可以选择简单地更新这些列,从而减少条目数... 我们还没有最终决定,但这肯定也在我们的关注范围之内。 - prodigitalson
我知道这是一个老的回答,但我想指出 bigint(20) 实际上并不限制列数据大小;它只控制了zerofill选项以控制前导零。 - Omar Dulaimi

1

情况:当所有用户活动都有不同的表时。例如,点赞、评论、发布、成为会员等。

那么这些表应该有一个键将条目与用户关联起来。给定一个用户,您可以通过按用户键查询每个表来获取最近的活动。

因此,如果您还没有架构或者您有特权更改它,请使用不同的表格进行不同的活动,并搜索多个活动。

情况:有一些活动是通用的,没有单独的表格

然后为通用活动设置表格,并与其他活动表格一起搜索。


0
你需要存储每个用户的具体活动,还是只想记录随时间发生的活动类型?如果是后者,那么你可以考虑使用类似RRDtool的工具,并将不同时间步长内的活动量存储在一个循环缓冲区中,其大小随时间保持恒定。请参见http://en.wikipedia.org/wiki/RRDtool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接