【问题标题】:Stores millions of daily IP address logs存储数百万个每日 IP 地址日志
【发布时间】:2013-06-10 18:13:55
【问题描述】:

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

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

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

我们还需要每日统计前 10 个 IP 地址点击量。

这是我用 MySQL 得到的,但我们的问题是数据库变得越来越重,占用了很大的空间。

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

目前,如果我选择好的数据结构,我会将每个点击存储为行,那么我的问题将解决

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

而且必须节省存储空间

【问题讨论】:

  • 您将访问日志存储多长时间?统计数据只需要一天,还是永久保留?
  • 尝试升级到付费版本或其他数据库供应商。
  • 长长的比过去 1 年还要大
  • 请告诉我们确切的 DDL。您是否使用BINARY 类型作为 IP 地址?此外,您是否需要存储每次点击,还是只存储一段时间内的汇总点击?
  • 听起来你的表基本上是两列:IP 和请求时间?如果一天是最低级别的详细信息,您可以制作这三列:IP、日期和请求计数。或者,您可以有一个历史记录表,您可以在其中每天汇总信息。

标签: mysql database-design data-structures


【解决方案1】:

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

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

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

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

更新:

是的,所以上面的所有内容都是压缩来自同一 IP 地址的多个命中。与唯一命中相比,这显然更有效,您获得的重复命中越多。如果您只关心独特的点击,则完全无关紧要。

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

这样,每个 IP 使用 4 个字节而不是字符串;此时存储外键(无论如何至少需要 4 个字节)是没有用的。因此,您可以只拥有一个包含字段的非规范化表:(IPv4 作为编码的无符号整数,日期时间/时间戳作为 4 字节整数)。您可能会用一天和一个计数替换日期时间,具体取决于您是否计算多次点击。如果多次点击不算数,你真的可以用一个 int 表示 IP 和一个 int 表示日期。

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

您还可以将时间(或时间段)展平/非规范化为 int(甚至更小),具体取决于您希望记录时间的频率/粒度,以及您是否选择聚合/归档/清除定期IP db表。

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

【讨论】:

  • 对于大数据问题(以及这里的低数据复杂性和关系),我永远不会继续使用基于 RDBMS 的架构。但是,是的。或许可以对 MySQL 进行调整和调整,使其勉强过关。
  • @tbsalling,是的,但关键是,如果您能够将数据压缩到其原始大小的一小部分,它就不再是“大数据”,尤其是当它小几个数量级时。事实上,如果你能将它压缩到小得多的尺寸,那么它不仅可以避免技术堆栈的错误转变,而且可以节省大量金钱和电力,甚至可能更快。对问题使用流行语是解决问题的一种非常暴力的方法。
  • @tbsalling 此外,我的解决方案是一种有损压缩和数据规范化的形式,而不仅仅是“调整”和“玩弄”,也与 MySQL 甚至 RDBMS 没有任何关系。事实上,您可以并且可能应该在 NoSQL 表示之上进行类似的优化。在某些性能和成本指标上进行竞争时,正是这些“调整”和“扭曲”有助于将顶级公司与其他公司区分开来。从你拥有的资源中榨取更多资源是优秀软件工程的基石;将趋势技术用于解决问题是幼稚的。
  • 但是这个解决方案仍然不节省存储空间
【解决方案2】:

如果您可以将数据库从 MySQL 等 RDBMS 技术中更改出来,那么您绝对应该看看 NoSQL 数据库,例如CouchDBCassandraRIAK

这些将根据您的需求进行扩展 - 但其工作方式与 SQL 数据库完全不同 - 因此需要一些学习曲线。

我可以推荐看看“7 databases in 7 weeks”一书以了解崩溃开始。

【讨论】:

  • 不妨建议尝试重置计算机/服务器。你根本没有解释 NoSQL 将如何帮助这种特殊情况
  • 好吧,我确实为提问者指明了一个有用的方向。在不知道 NoSQL 是否完全适合他的情况下,贴一堵解释 NoSQL 如何为他工作的文字墙几乎没有意义。 SO 是一个很好的提问场所 - 但一个充满敌意的回答场所!
  • 几乎没有。关键是 OP 正在询问有关 RDBMS 中的信息压缩的问题,并且在该空间 (MySQL) 中有直接且明显的解决方案。这就像询问用 C++ 读取文件的最佳方法,有人说尝试使用 Python。列出一堆相关技术并不是特别有用,尤其是在没有投入任何努力甚至暗示它们可能提供帮助的情况下。
  • 我无法读出原始问题,MySQL 是解决方案的固定部分。 OP 甚至不带有 MySQL 标签。没有更多的 cmets。
  • 这并没有改变您甚至没有暗示您的替代 dbms 将如何帮助 OP 解决性能/内存/扩展问题的事实。您可以轻松地将这个响应复制粘贴到有关 RDBMS 的每个问题中。 “嘿,试试另一种 DBMS 技术,也许它的性能会更好。祝你好运!”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
相关资源
最近更新 更多