保存在MongoDB中的IP地址(save IP address in mongoDB)

2019-07-22 22:37发布

目前,为了节省IP地址,我将其转换成数,并将其保存收藏。 基本上我对记录的目的这样做。 这意味着,我关心存储的信息尽可能快地与空间的最小量。

我将很少使用它进行查询。

我的想法,

  • 存储为字符串是肯定的低效。
  • 存储为4位将变慢并且将需要更多的空间。

但是我认为这是一个适当的方法,但有一个更好的为我的目的是什么?

Answer 1:

绝对的IP地址保存为数字,如果你不介意的话,它需要工作的额外位,特别是如果你需要做的查询上的地址,你有大的表/集合。

这是因为:

存储

  • IPv4地址是4个字节,如果存储为无符号整数。
  • 当如虚线octed形式的字符串写到10个字节和18个字节之间的IPv4地址而变化。 (假设平均是14个字节)。

这是7-15字节字符,再加上如果您使用的是可变长度的字符串类型,这取决于您所正在使用的数据库2-3个字节。 如果你有一个固定长度的字符串表示可用,那么你必须使用一个15个字符的固定宽度的字段。

磁盘存储很便宜,所以这不是在大多数使用情况的一个因素。 记忆,但是,是不是因为便宜,如果你有一个大表/收集和你想要做的快速查询,那么你就需要一个索引。 字符串编码的2-3倍罚款存储大大减少的,你可以指数,同时仍保持指数驻留在内存中记录的金额。

  • IPv6地址为16个字节,如果存储为无符号整数。 (几率是多4个或8个字节的整数,根据您的平台。)
  • 当如在缩写十六进制表示法的字符串所编码的IPv6地址由6个字节至42个字节的范围内。

在低端,环回地址(:: 1)是3个字节加上可变长度字符串开销。 在高端,如地址2002:4559:1FE2:1FE2:4559:1FE2:4559:1FE2使用39个字节加上可变长度字符串开销。

不像IPv4的,这不是安全的假设平均IPv6的字符串长度为平均值的6和42,因为连续零的显著数量的地址数量是整个IPv6地址空间的很小一部分。 只有一些特殊的地址,如环回和autoconf地址,很可能是用这种方式压缩。

再次,这是> 2倍的字符串编码与整数编码的存储惩罚。

网络数学

你认为路由器店IP地址为字符串? 当然,他们不知道。

如果您需要做IP地址的网络数学,字符串表示是一件麻烦事。 例如,如果您想编写一个查询,搜索特定子网上的所有地址(用一个整数子网掩码屏蔽整数地址“的IP地址返回的所有记录在10.7.200.104/27”,你可以很容易地做到这一点。 (蒙戈不支持此特定的查询,但大多数RDBMS做的。)如果存储地址为字符串,然后将查询需要将每一行转换为整数,然后掩盖它,这是幅度比较慢几个数量级。(按位掩蔽为IPv4地址可以使用2个寄存器几个CPU周期来完成。将字符串转换为一个整数,需要遍历的字符串。)

同样,范围查询(“返回所有记录192.168.1.50和192.168.50.100之间的所有记录”)与整数地址就可以使用索引,而范围查询字符串地址不会。

底线

它需要更多一点的工作,但不是很多(有100万航标()和ntoa()函数在那里),但如果你正在构建什么大不了的事情做实要面向未来其对未来的需求和大型数据集的可能性,你应该IP地址存储为整数,而不是字符串。

如果你正在做一些快速和肮脏的,不介意在未来重塑的可能性,然后使用字符串。

对于OP的目的,如果你在优化速度和空间,你不认为你要经常查询它,那么为什么要使用一个数据库呢? 只是打印IP地址到一个文件中。 这将是更快,更比存储在数据库中存储它(与相关的API和存储开销)有效。



Answer 2:

一种有效的方式,一个IP地址保存为INT。 如果你想标记与CIDR过滤器,演示这里IP:

> db.getCollection('iptag').insert({tags: ['office'], hostmin: 2886991873, hostmax: 2887057406, cidr: '172.20.0.0/16'})
> db.getCollection('iptag').insert({tags: ['server'], hostmin: 173867009, hostmax: 173932542, cidr: '10.93.0.0/16'})
> db.getCollection('iptag').insert({tags: ['server'], hostmin: 173932545, hostmax: 173998078, cidr: '10.94.0.0/16'})

创建标签指数。

> db.getCollection('iptag').ensureIndex(tags: 1)

过滤IP与CIDR范围。 ip2int('10.94.25.32') == 173938976

> db.getCollection('iptag').find({hostmin: {$lte: 173938976}, hostmax: {$gte: 173938976}})


Answer 3:

一个IPv4是四个字节,所以可以将其存储到一个32位的整数(BSON类型16)。

见http://docs.mongodb.org/manual/reference/bson-types



Answer 4:

IPv4的最简单的方法是转换使用提供有趣的数学为int 这里 。

我使用下面的函数(JS)与数据库匹配之前转换

ipv4Number: function (ip) {
    iparray = ip.split(".");
    ipnumber = parseInt(iparray[3]) +
        parseInt(iparray[2]) * 256 +
        parseInt(iparray[1]) * Math.pow(256, 2) +
        parseInt(iparray[0]) * Math.pow(256, 3);
    if (parseInt(ipnumber) > 0)return ipnumber;
    return 0;
}


文章来源: save IP address in mongoDB