It has been 731 days since the last update, the content of the article may be outdated.
今天在项目开发时,遇到需要在数据库中存储 ip 地址,那么应该选用何种数据类型更加高效呢?
如果存储的是IPV4
地址,可以选择使用INT UNSIGNED
,然后借助 MySQL
自带的 INET_ATON()
和 INET_NTOA()
来存取数据;
如果存储的是IPV6
地址,可以选择使用VARBINARY()
,然后借助 INET6_ATON()
和INET6_NTOA()
(MySQL5.6+
支持)方法存取数据。
针对IPv4
地址
sql
mysql> select inet_aton('127.0.0.1'); |
数据存取
存数据
sqlINSERT INTO `ip_addresses` (`ip_address`)
VALUES (INET_ATON('127.0.0.1'));取数据
sqlSELECT id, INET_NTOA(`ip_address`) AS ip
FROM `ip_addresses`;Python
实现
对于上面的代码,如果我们不想使用内置的MySQL
方法,也可以在应用层使用自己封装的方法:
python
import socket, struct |
更新
我们还可以使用 ipaddress 库对 ip 地址进行 int 和 str 之间的互转。代码如下:
python
import ipaddress |
针对IPv6
地址
MySQL 提供内置函数inet6_aton()
来存储和检索IPv6
地址。敲黑板,不要把IPv6
地址存储为整数,因为数字格式的IPv6
地址需要比UNSIGNED BIGINT
更多的字节。所以下面的函数返回VARBINARY(16)
数据类型。让我们看一个例子。
sql
mysql> select hex(inet6_aton('127.0.0.1')); |
注意
假设你正在编写查找以ip
地址为127.0.0.1
连接的用户,可能写出如下的查询语句:
sql
SELECT name FROM user WHERE inet_ntoa(ipaddress)='127.0.0.1'; |
请注意,此查询不会使用在ipaddress
列上创建的索引,因为我们在SQL
执行期间修改了索引列,它也会逐行将整数转换为真实的IP
地址。所以要想让索引生效应该:
sql
SET @ip = inet_aton('127.0.0.1'); |
或者
sql
SELECT name FROM user WHERE ipaddress = inet_aton('127.0.0.1'); |