存储数百万的每日IP地址日志

时间:2013-06-14 06:50:06

标签: mysql database-design data-structures

我们有一个点击跟踪系统,我跟踪每个请求的IP地址。

每天我们都会获得数百万次点击。

对于每个请求并在MySQL中将IP地址存储为1行

我们还需要每日统计数据排名前10位的IP地址。

我正在使用MySQL,但我们的问题是数据库变得越来越重,并占用大量空间。

我正在寻找能够以有效方式存储此IP地址的良好“数据结构”吗?

目前我将每个匹配存储为行,如果我选择了良好的数据结构,那么我的问题将解决

我不想运行复杂的查询,但每天前10名,每周IP地址前10名。

并且必须保存存储空间

2 个答案:

答案 0 :(得分:0)

如果您不需要每个ip访问时间戳都精确到秒,您可以将每一天划分为一系列时间段(可能每10或5分钟一段)。每个日期时段在时间段表中都有一个id。然后,您可以为ip表中的每个唯一IP地址创建一个id。

然后你有一个连接表,你用一个计数(无符号整数)将IP地址(外键)与时间段(外键)相关联。因此,您的核心访问行数据现在简化为2个ID和1个无符号整数(最重要的是,没有字符串)。

因此,当您收到来自IP的请求时,您将确定当前时间段,并在该时间段不存在时为新时间段创建一行。如果当前时间段与IP无关,则创建一个计数为1的新行。如果此时间段和IP有一行,则递增计数。

通过这种方式对数据/表进行规范化,并略微降低准确性,您可以实现一种信息压缩形式。玩弄时间段间隔以找到最佳权衡。例如。如果您不需要几分钟甚至几小时的查询粒度,您可以将您的时间段缩短一天。

<强>更新

是的,所以上面的所有内容都是压缩来自同一IP地址的多次点击。与独特的点击相比,这显然更有效。如果你只关心独特的命中,那就完全无关紧要了。

有多种方法可以将IPv4地址压缩为无符号整数(32位)。只需将每个a.b.c.d部分分别移位到字节0xff0000000x00ff00000x0000ff000x000000ff

这样,每个IP使用4个字节而不是字符串;此时存储外键没有用处(至少需要4个字节)。所以你可以只有一个带有字段的非规范化表:( IPv4作为编码的unsigned int,datetime / timestamp作为4字节int)。您可以使用日期和计数替换日期时间,具体取决于是否有多个匹配计数。如果多次点击不计算,你可能真的只能使用IP的int和日期的int。

如果day-granulartiy是您所需的最低值,则可以选择更进一步的选项:您可以在每天结束时清除此IP db表,并仅将聚合查询的结果存储在数据库中。其余数据可以每天存档并从IP db表中删除。这意味着您的表只需要是一个字段:编码的IP作为unsigned int。在这一点上,问题只是每天构建一组大量独特的整数。

您还可以将时间(或时间段)压缩/非规范化为int(或更小),具体取决于您想要记录时间的频率/粒度,以及是否选择聚合/存档/清除定期使用IP db表。

以压缩方式存储多个IP地址的另一种方法是使用trie数据结构,但它不直接映射到数据库存储(与内存数据结构相比)。通过SQL存储树结构(例如trie)的一种方法是使用Materialized Path方法 - 但是,此方法无法实现良好的数据压缩,并且查询开销可能不值得。

答案 1 :(得分:-1)

如果你可以改变数据库远离MySQL这样的RDBMS技术,那么你一定要看看NoSQL数据库,例如 CouchDB Cassandra RIAK

这些可以扩展到您的需求 - 但是以与SQL数据库完全不同的方式工作 - 因此需要一些学习曲线。

我建议您查看“7 databases in 7 weeks”一书,了解崩溃的开始。