存储IP地址,到底用什么数据类型相对比较好

一、 介绍

在平常开发当中,肯定遇到过需要存储IP地址的场景,比如登录、访问、操作日志记录,方便起见直接使用字符串类型存储也不是不可以,但是在《高性能MySQL》中,建议存储IPv4地址时,使用32位无符号整数类型,而不建议使用字符串类型。

二、使用无符号整数类型存储IP的优点

  • 节省存储空间和索引空间
  • 便于使用范围查询,如:between...and,而且查询效率更高

通常,我们保存IPv4地址时,一个IPv4最小需要7个字符(四个一位数数字,三个点),最大需要15个字符(三个三位数,三个点),因此使用varchar(15)就可以满足存储要求。MySQL在保存变长的字符串时,还需要额外的一个字节来保存此字符串的长度。而如果使用无符号整数来存储,只需要4个字节即可。另外还可以使用4个字段分别存储IPv4中的各部分,但是通常这不管是存储空间和查询效率都不会很高,如果确实有这种应用场景,可以采取这种做法。

三、使用无符号整数类型存储IP的缺点

  • 可读性差
  • 需要开发人员手动转换处理

四、SQL转换

对于转换来说,MySQL提供了相应的函数,使用INET_ATON可以将字符串形式的IP转换成整数,使用INET_NTOA可以将整数格式的IP转换成可读的字符串,如下演示:
存储IP地址,到底用什么数据类型相对比较好_第1张图片
存储IP地址,到底用什么数据类型相对比较好_第2张图片
对于IPv6来说,使用varbinary类型同样可以得到同样的字符串类型存储效果,同时MySQL也提供了相应的转换函数,即INET6_ATONINET6_NTOA

五、Java转换

转换操作也可以可以放在应用层,以Java代码为例:

/**
 * IP工具类
 *
 * @author zhangxs
 **/
public class IPUtils {
    /**
     * 把字符串IP转换成long
     * @param ip 字符串IP
     * @return long
     * @author zhangxs
     * @date 2021-08-10 10:13
     */
    public static long ipToLong(String ip) {
        String[] el = ip.split("\\.");
        return (Long.parseLong(el[0]) << 24) + (Long.parseLong(el[1]) << 16)
                + (Long.parseLong(el[2]) << 8) + (Long.parseLong(el[3]));
    }

    /**
     * 把IP的long值转换成字符串
     * @param longIp long类型IP
     * @return java.lang.String
     * @author zhangxs
     * @date 2021-08-10 10:15
     */
    public static String longToIp(long longIp) {
        return (longIp >>> 24) + "." +
                ((longIp >>> 16) & 0xFF) + "." +
                ((longIp >>> 8) & 0xFF) + "." +
                (longIp & 0xFF);
    }

    public static void main(String[] args) {
        System.out.println(ipToLong("10.18.28.76"));
        System.out.println(ipToLong("10.0.0.1"));
        System.out.println(longToIp(168959052L));
    }
}

测试结果:

168959052
167772161
10.18.28.76

六、总结

使用字符串和无符号整数来存储IP的具体性能分析及benchmark,参考文章献上,呐。

你可能感兴趣的:(Java,SQL,字符串,数据库)