用于跟踪 IPv6/IPv4 个地址的关系数据库——我提议的模式是否有效?

Relational database for tracking IPv6/IPv4 addresses -- will my proposed schema work?

背景

我正在构建一个 IPAM 应用程序来跟踪和存储各个 IPv4 和 IPv6 地址的元数据。后端旨在成为一个无聊的、与供应商无关的关系数据库。

IPv6 可以在巨大的可寻址范围内处理大量数据 space,但所讨论的范围本身并不构成大数据,所以如果我的技术存在一些实际缺陷,我不愿意更改后端架构当前的方法最好由时髦的 NoSQL 解决方案提供,但代价是关系和 ACIDity。

(我不是要记录整个地址 space,只是任意客户使用的实时地址。)

架构

规范化给定 IP 地址的字符串表示形式并将其用作主键。 IPv4 地址被转换为 IPv6 并以 ffff 为前缀。 IPv6 地址被压缩和小写。

第二个字段指示相关记录是哪个协议版本——4 或 6。这里的想法是,如果用户在 IPv4 子网中搜索记录,我可以快速排除 IPv6 space ,反之亦然。

接下来的八个字段 (ugh) 都是地址中每个八位字节的整数表示(octet_1octet_2 等)。

索引

主键应该已经是它自己的唯一索引。

(version, octet_1, ..., octet_8) 上创建一个附加索引。

正在查询

为了搜索任一版本的特定 IP,我可以简单地按照与上述相同的方式规范化 IP 字符串并通过主键搜索。

为了按子网搜索,应用程序计算范围的 start/end 地址,将两者都转换为 IPv6,将两者都转换为八元组,并查询所有包含八元组的记录。

我 运行 使用这种方法可能会遇到什么问题?改进建议?

ipv4s casted as ipv6 are not the same thingyour index will explode / write performance will suck 的任何内容都是公平的游戏。

我构建了一个测试 POC 来验证此模式的功能,但我担心此模型在生产环境中的任何潜在缺点。

如果你可以选择数据库后端,那就选择 PostgreSQL。它内置了 IP 地址类型,因此提供了出色的性能和功能。

但是您说过您想成为数据库不可知论者,所以让我们专注于此。在那种情况下,我将仅使用以 ::ffff: 为前缀的 IPv4 地址进行字符串表示,但随后仅使用小写十六进制表示法并且不进行压缩。所以 IPv4 地址 10.11.12.13 将变为 0000:0000:0000:0000:0000:ffff:0a0b:0c0d.

几乎所有的数据库都有良好的字符串索引,使用这种表示法您可以轻松地进行子网和范围查询。如果您想要所有 IPv4 地址,只需查询 LIKE '0000:0000:0000:0000:0000:ffff:%'。因为它是在开始时锚定的,所以标准的 btree 索引应该运行良好。您可以使用 < 和 > 运算符对范围进行更复杂的查询,这同样可以从标准索引中受益。这应该会为您提供大多数子网查询。

在您的应用程序中,使用 inet_pton 等解析字符串以将它们转换为您需要的任何内容应该不会太难。

在这种情况下我会避免反规范化。使用我上面描述的内容,您不需要单独的版本或八位字节列。它们只会减慢速度并增加不一致的可能性。

在 "Schema" 下,您尚未提供实际架构。

"IPv4 addresses get converted to IPv6 and prefixed with ..." 暴露你不理解 IPV6 的意图和目的。

"IPv6 addresses get ... lowercased." 表明您不了解值和值表示之间的区别("get lowercased" 可能会影响 表示 的值,但它 永远不会 影响 值本身).

"if a user searches for records in an IPv4 subnet" 表明您不了解 OSI 7 层模型的构思者在构思其网络通信模型时所考虑的关注点分离。 "Searching for records"与IP(v4/v6)不是同层函数。

"Primary key should already be its own unique index." 暴露你不懂关系型数据管理

您可能会觉得这不是您问题的答案,但实际上它是。