在《高性能MySQL》第3版中,作者建议使用32位无符号整数(UNSIGNED INT)来存储IPv4地址而不是字符串,这一建议基于多个原因,下面将详细分析这些原因,并提供一些额外的背景信息和实用代码。

使用无符号整数存储IPv4地址的好处

  1. 节省空间

    • 数据存储空间:IPv4地址作为字符串存储时,最小需要7个字符,最大15个字符,加上MySQL存储变长字符串所需的额外字节,平均需要14.28字节。而使用无符号整数存储,仅需要4字节。
    • 索引存储空间:整数类型的索引通常比字符串类型的索引小,这意味着索引可以更快地被存储和查询。
  2. 查询效率

    • 使用无符号整数存储IPv4地址可以方便地使用范围查询(如BETWEEN...AND),且效率更高。字符串类型的IP地址进行范围查询时,需要额外的函数转换,效率较低。
  3. 性能

使用无符号整数存储的缺点

  1. 不便于阅读:整数形式的IP地址不如字符串形式直观,不便于人工阅读和理解。

  2. 需要手动转换:在应用层需要进行字符串和整数之间的转换。

MySQL中的转换函数

  • INET_ATON:将字符串格式的IP转换为整数。
  • INET_NTOA:将整数格式的IP转换为字符串。
mysql> select inet_aton('192.168.0.1');
+--------------------------+
| inet_aton('192.168.0.1') |
+--------------------------+
|               3232235521 |
+--------------------------+
1 row in set (0.00 sec)

mysql> select inet_ntoa(3232235521);
+-----------------------+
| inet_ntoa(3232235521) |
+-----------------------+
| 192.168.0.1           |
+-----------------------+
1 row in set (0.00 sec)

Java中的转换代码

下面的Java代码展示了如何在应用层进行字符串IP和整数之间的转换:

public class IpLongUtils {
    /**
     * 把字符串IP转换成long
     *
     * @param ipStr 字符串IP
     * @return IP对应的long值
     */
    public static long ip2Long(String ipStr) {
        String[] ip = ipStr.split("\\.");
        return (Long.valueOf(ip[0]) << 24) + (Long.valueOf(ip[1]) << 16)
                + (Long.valueOf(ip[2]) << 8) + Long.valueOf(ip[3]);
    }

    /**
     * 把IP的long值转换成字符串
     *
     * @param ipLong IP的long值
     * @return long值对应的字符串
     */
    public static String long2Ip(long ipLong) {
        StringBuilder ip = new StringBuilder();
        ip.append(ipLong >>> 24).append(".");
        ip.append((ipLong >>> 16) & 0xFF).append(".");
        ip.append((ipLong >>> 8) & 0xFF).append(".");
        ip.append(ipLong & 0xFF);
        return ip.toString();
    }

    public static void main(String[] args) {
        System.out.println(ip2Long("192.168.0.1"));
        System.out.println(long2Ip(3232235521L));
        System.out.println(ip2Long("10.0.0.1"));
    }
}

输出结果

3232235521
192.168.0.1
167772161

结论

尽管使用无符号整数存储IPv4地址在可读性和转换上存在一定的不便,但从性能和存储效率的角度考虑,这种方法具有明显的优势。特别是在进行大量IP地址范围查询的应用场景中,使用整数存储可以显著提高查询效率和减少存储空间的使用。对于新的数据库设计,推荐使用无符号整数来存储IPv4地址。

上一篇 下一篇