0

我有一个非常简单的表格来跟踪用户活动。它的结构如下:

userId appId lastActivity

PRIMARY(userId, appId)

表允许跟踪用户是否在特定应用程序中处于活动状态。它为每个用户每分钟更新一次,并经常阅读以计算特定应用程序中在线用户的数量。

最近我注意到,更新需要一段时间才能执行:

2012-10-01 16:49:10 - WARN --> Heavy query; array (
  'caller' => 'updateActivity',
  'query' => 'INSERT INTO user_activity VALUES(4953, 1, 1349095750)
                  ON DUPLICATE KEY UPDATE lastActivity = 1349095750',
  'elapsed' => 0.134618,
)
2012-10-01 18:26:06 - WARN --> Heavy query; array (
  'caller' => 'updateActivity',
  'query' => 'INSERT INTO user_activity VALUES(4533, 1, 1349101566)
                  ON DUPLICATE KEY UPDATE lastActivity = 1349101566',
  'elapsed' => 0.581776,
)
2012-10-01 18:27:16 - WARN --> Heavy query; array (
  'caller' => 'updateActivity',
  'query' => 'INSERT INTO user_activity VALUES(5590, 1, 1349101636)
                  ON DUPLICATE KEY UPDATE lastActivity = 1349101636',
  'elapsed' => 0.351321,
)
2012-10-01 20:54:32 - WARN --> Heavy query; array (
  'caller' => 'updateActivity',
  'query' => 'INSERT INTO user_activity VALUES(3726, 1, 1349110472)
                  ON DUPLICATE KEY UPDATE lastActivity = 1349110472',
  'elapsed' => 0.758706,
)

表使用 InnoDB 作为存储引擎。

我的问题

  1. 有什么问题吗?

  2. 我的设计有问题吗?

  3. 在这种特定情况下从哪里开始寻找性能问题?

4

1 回答 1

0

好吧,它是 InnoDb,它的性能不如 MyISAM(取决于插入的频率)您正在尝试在此处实现事件日志记录模型。如果您想生成有用的长期(甚至是中期)统计数据,您的模型将会失败,因为它基本上会忘记上次发生的所有事情。我建议你重新实现

  1. 丢失该update on duplicate子句并简单地为每个活动/事件执行新的插入。您减少了更新活动的开销。
  2. 将您的 InnoDb 引擎转换为 MyISAM,那里的性能也得到提升

  3. 如果进行以上两个,PK就变得没有必要了。就目前而言,它的用途值得怀疑。也许您应该立即获取Unique索引。

所有这一切给你留下的只是一个高效的日志系统,它有能力变得相当大。有批量归档选项可以进一步处理该问题

于 2012-10-04T05:31:15.933 回答