在mongoDB中保存IP地址

Sal*_*ali 13 ip-address mongodb

目前为了保存IP地址,我将其转换为数字并将其存储在集合中.基本上我这样做是为了记录日志.这意味着我尽可能快地存储信息并且空间最小.

我很少用它来查询.

我的想法

  • 存储为字符串肯定是低效的.
  • 存储为4位数将会更慢并且将占用更多空间.

尽管如此,我认为这是一个适当的方法,但是有一个更好的方法吗?

Mar*_*ase 11

绝对将IP地址保存为数字,如果你不介意它需要额外的工作,特别是如果你需要对地址进行查询并且你有大型表/集合.

原因如下:

存储

  • 如果存储为无符号整数,则IPv4地址为4个字节.
  • 当以点分隔形式写成字符串时,IPv4地址在10字节和18字节之间变化.(假设平均值是14个字节.)

对于字符,这是7-15个字节,如果您使用的是可变长度字符串类型,则会增加2-3个字节,这取决于您正在使用的数据库.如果您有可用的固定长度字符串表示,则必须使用15个字符的固定宽度字段.

磁盘存储很便宜,因此在大多数用例中并不是一个因素.但是,内存并不便宜,如果你有一个大型表/集合并且想要快速查询,那么你需要一个索引.字符串编码的2-3x存储代价大大减少了您可以索引的记录数量,同时仍保持索引驻留在内存中.

  • 如果存储为无符号整数,则IPv6地址为16个字节.(可能是多个4或8字节整数,具体取决于您的平台.)
  • 当以十六进制表示法编码为字符串时,IPv6地址的范围为6个字节到42个字节.

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

与IPv4不同,假设平均IPv6字符串长度为6和42的平均值是不安全的,因为具有大量连续零的地址数量只占整个IPv6地址空间的很小一部分.只有一些特殊地址(如loopback和autoconf地址)可能以这种方式可压缩.

同样,对于字符串编码与整数编码,这是一个> 2x的存储损失.

网络数学

您认为路由器将IP地址存储为字符串吗?当然他们没有.

如果您需要对IP地址进行网络数学运算,则字符串表示很麻烦.例如,如果要编写一个搜索特定子网上所有地址的查询("返回IP地址在10.7.200.104/27中的所有记录"),则可以通过使用整数子网掩码屏蔽整数地址来轻松完成此操作. (Mongo不支持这个特定的查询,但是大多数RDBMS都这样做.)如果你将地址存储为字符串,那么你的查询需要将每一行转换为一个整数,然后屏蔽它,这要慢几个数量级.(按位)使用2个寄存器可以在几个CPU周期内完成对IPv4地址的屏蔽.将字符串转换为整数需要在字符串上循环.)

类似地,使用整数地址的范围查询("返回所有记录在192.168.1.50和192.168.50.100之间的所有记录")将能够使用索引,而字符串地址上的范围查询则不能.

底线

它需要更多的工作,但不多(有一百万aton()和ntoa()函数在那里),但如果你正在构建一些严肃而坚实的东西,并且你希望将来证明它符合未来的要求和大数据集的可能性,您应该将IP地址存储为整数,而不是字符串.

如果你正在做一些快速和肮脏的事情,并且不介意将来重塑的可能性,那么使用字符串.

对于OP的目的,如果您正在优化速度和空间并且您认为不想经常查询它,那么为什么要使用数据库呢?只需将IP地址打印到文件即可.这比将其存储在数据库中具有更快且更高的存储效率(具有相关的API和存储开销).