背景
我在我的小公司'继承'了一个php webapp 经过多年的唠叨终于得到了 去掉意大利面条代码然后重新开始。
我们希望记录系统中的每个操作,例如:
以后提供不同分辨率(日,月,年)的图表 在系统中完成的操作。
在之前的版本中,我们有一张表,其中有20,000,000条记录 2005年,这将让您了解我们已经拥有的大量数据 有,这只是众多统计数据之一。
实际问题:
您建立近实时的建议 系统来创建这个统计数据?
备注:
答案 0 :(得分:2)
如果所有用户都必须注册,我会使用完整的规范化解决方案。
USERS TABLE OBJECTS TABLE
--------------- -----------------
user_id (primary) object_id (primary)
USERS_TO_OBJECTS TABLE
--------------------
user_id (index)
object_id (index)
time (index)
action (index)
? object_type (index) // could be useful to speed things up
这种设置可能会在制图时为您提供最大的灵活性,并且也会非常快,因为如果您不需要它们,可以省略用户或对象。
修改强>
假设城市X(id 9876)由用户123(id 1234)更新......
1234 - user_id (the user that did the action)
9876 - object_id (the object where the action was done)
xyz - time
updated - action type (so that you select only specific actions)
city - object type (so that you select only specific objects)
我已经用40M行填充了这个表,结果非常可接受。
对于上一周的UPDATED城市数量的简单COUNT,为0.002秒。随机插入数据。
修改2
如果你发现自己有一个非常庞大的表,你可以使用MySQL分区,你的架构是完美的。我真的不知道你将如何使用这些表,但你可以:
按范围划分。在日期上组织分区。每个新的一个月左右你都会有一个新的分区。
按键分区。按操作组织分区。每个动作都适用于它的正确分区。
您可以将more on partitions on MySQL's site和this article gives you some detail签入微调分区。
答案 1 :(得分:1)
你可以考虑像Redis这样的“数据库”。 Redis使用链接列表来存储列表类型,因此您可以轻松地将LPUSH添加到如下列表中:
$action = array(
"type"=>"page_view",
"url"=>"/example/path",
"user"=>"user1",
"timestamp"=>$_SERVER["REQUEST_TIME"]
);
$r = new Redis();
// Redis connection info //
$r->lPush("global_history", json_encode($action));
LPUSH操作在O(1)
运行,因此不应成为问题。检索结果可能有点棘手(列表的O(n)
时间)。 Redis也主要基于内存(虽然开发版包括“虚拟内存”支持),所以它很快,但你可以很容易地用完房间。
我使用此技术记录我运行的音乐网站的历史记录和统计信息。它非常成功,只需很少的努力即可提供非常快速的结果。
如果您想让它更加稳固,您可以使用Hadoop或其他技术从列表末尾(RPOP)提取并将结果归档为更永久的格式(例如,XML推送到Amazon S3)。然后,您可以在查看旧数据时使用Google可视化文件从存档中查找数据(这将是静态的,已编译的数据),而在Redis前端查找更新的数据。
希望这有帮助!
答案 2 :(得分:0)
我很高兴你终于得到了重新设计该项目的绿灯。可能在这里回复太迟了,但MongoDB(带有Capped Collections功能)的实现可以更好地完成这种工作。实现它并不太费时,所以也许还有机会。
无论如何,希望一切顺利。