君哥聊技术

面试官:数据库怎样保存 IP 地址?

大家好,我是君哥。

数据库保存 IP 地址是偶尔会遇到的存储场景,今天来聊一聊数据库怎样保存 IP 地址。

PostgreSQL

PostgreSQL 使用 INET 类型存储 IP 地址,IPv4 或 IPv6 都可以存储,同时也可以存储子网信息。

存储格式为 IP/子网掩码位数,比如:192.168.1.1/24。插入 SQL 如下:

INSERTINTO ip_test(id, ip) VALUES (1, '192.168.1.1/24');

INET 类型可以对 IP 地址进行输入校验、子网包含判断等操作,提升数据完整性和查询效率。比如下面语句判断子网是否包含,结果返回 true:

SELECT'192.168.1.5'::inet << '192.168.1.0/24'::inet;

MySQL

MySQL 可以使用 VARCHAR 类型保存 IP 地址,但是并不推荐,因为 MySQL 提供了专门的保存 IP 地址的数据类型。

IPV4

MySQL 推荐使用 INT UNSIGNED 类型保存 IPV4 地址,并且提供了专门的函数 INET_ATON(将 IP 转为整数)和 INET_NTOA(将整数转为 IP) 进行转换。首先我们创建一张表:

CREATETABLE`ip_test` (
`id`bigint(20) NOTNULL AUTO_INCREMENT,
`ip`int(10) unsignedDEFAULTNULL,
KEY`id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2DEFAULTCHARSET=utf8 COLLATE=utf8_bin

下面 SQL 是插入和查询的实例:

--插入
INSERTINTO ip_test VALUES(1,INET_ATON('192.168.1.5'));
--查询
SELECTid, INET_NTOA(ip) FROM ip_test;

使用 INT UNSIGNED 类型保存 IPV4 地址,有如下好处:

  • 存储空间更小,仅 4 个字节;
  • 支持范围查询和索引优化,查询性能更好。

IPv6

对于 IPv6 类型地址,MySQL 可以使用 VARBINARY(16) 类型存储,并且提供了 INET6_ATON 和 INET6_NTOA 函数进行转换。我们再创建一张保存 IPV6 地址的表:

CREATETABLE`ip_test_v6` (
`id`bigint(20) NOTNULL AUTO_INCREMENT,
`ip` varbinary(16) DEFAULTNULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDBDEFAULTCHARSET=utf8 COLLATE=utf8_bin

下面 SQL 是插入和查询的实例:

--插入
INSERTINTO ip_test_v6 (id,ip) VALUES (1, INET6_ATON('FC00:0:130F:0:0:9C0:876A:130B'));
--查询
SELECTid, INET6_NTOA(ip) FROM ip_test_v6;

总结

主流数据库一般不推荐直接使用 VARCHAR 类型来存储 IP 地址,而是提供了内置的类型和函数,存储和查询效率更高。

精品专栏 70 篇,推荐阅读。
又老性能又差,为什么好多公司依然选择 RabbitMQ?

45 个知识点,带你入门消息队列!

引入了 Disruptor 后,系统性能大幅提升!

 从 MySQL 迁移到 GoldenDB,上来就踩了一个坑。

面试官:MySQL Redo Log 和 Undo Log 有什么区别?分别用在什么场景?

感谢阅读,如果对你有帮助,请点赞和在看。欢迎加我微信:zhujinjun86。

号内回复 seata,下载《阿里分布式中间件Seata从入门到精通》

号内回复 beijing,下载我总结的北京上百家知名科技公司

号内回复 aqs,下载《40张图精通Java AQS》