【问题标题】:php/mysql - logging users activities & huge database loadphp/mysql - 记录用户活动和巨大的数据库负载
【发布时间】:2011-08-07 00:13:23
【问题描述】:

假设我们必须记录一个社区的所有用户活动,我猜我们的数据库很快就会变得非常庞大;所以我的问题是:

为了提供这种服务,无论如何这是一个可接受的妥协(拥有一个巨大的数据库表)?或者我们可以以更有效的方式做到这一点?

编辑: 要记录的活动类型是“经典”社交网络活动日志,人们可以查看其他人正在做什么或做过什么,反之亦然,因此它会跟踪例如用户何时编辑个人资料、发布内容、登录,注销等。

编辑 2: 我的表已经优化,只存储id's

log_activity_table(
id int
user int 
ip varchar
event varchar #event-name
time varchar
callbacks text #some-info-from-the-triggered-event
)

【问题讨论】:

标签: php mysql logging android-activity


【解决方案1】:

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

对于我的项目,拥有完整的历史账目并不重要,因此我们选择保持表格相当精简,就像您正在做的那样。我们的表格如下所示:

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' 等。这些用于某些查询,当然也有助于确定要向用户显示的消息。

我们仍处于早期阶段,因此这可能会发生很大变化(可能基于 cmets 和此问题的答案),但考虑到我们的要求,这似乎是一个不错的方法。

【讨论】:

  • 是的,就像我们在做同样的事情一样;)我的问题是:例如,当某人正在编辑自己的个人资料并多次触发“保存更改”时,我们就有一堆无用的数据库条目,同样的事情发生在“登录”和“注销”,所以在这种情况下,我想我应该只是“更新”而不是“插入”,否则如果有人发表评论或新闻,我们会持续“插入” .你对此有什么看法? +1
  • @Julie:实际上我们只是在这个星期五讨论......我们正在讨论可能将实体类型从 subject 值对象序列化(或复制它)移动到它自己的列以及添加更新的 at 列。这样,我们可以选择简单地更新给定事件的 subjectupdated_at 列,如果它们在特定时间段内(比如 12-24 小时),从而导致更少的条目......我们还没有确定但这绝对在我们的雷达上。
  • 我知道这是一个旧答案,但我只是想指出bigint(20) 并没有真正限制列数据的大小;它只是控制 zerofill 选项来控制前面的零。
【解决方案2】:

案例:当所有用户活动都有不同的表时。例如。点赞、评论、发帖、成为会员。

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

因此,如果您还没有架构或者您有权更改它,请为不同的活动设置不同的表并搜索多个活动。

案例:有些活动是通用的,没有单独的表格

然后有通用活动表,并与其他活动表一起搜索。

【讨论】:

    【解决方案3】:

    您是否需要存储每个用户的具体活动,还是只想记录随时间发生的活动类型。如果是后者,那么您可能会考虑使用类似 RRDtool(或类似方法)的方法,并将不同时间步长的活动量存储在循环缓冲区中,其大小随时间保持不变。见http://en.wikipedia.org/wiki/RRDtool

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-22
      • 2012-03-07
      • 1970-01-01
      • 2011-02-28
      相关资源
      最近更新 更多