当前位置:网站首页>面试官:如果要存 IP 地址,用什么数据类型比较好?很多人都会答错
面试官:如果要存 IP 地址,用什么数据类型比较好?很多人都会答错
2022-08-07 06:35:00 【啊码】

在看高性能MySQL第3版(4.1.7节)时,作者建议当存储IPv4地址时,应该使用32位的无符号整数(UNSIGNED INT)来存储IP地址,而不是使用字符串。 但是没有给出具体原因。为了搞清楚这个原因,查了一些资料,记录下来。
相对字符串存储,使用无符号整数来存储有如下的好处:
- 节省空间,不管是数据存储空间,还是索引存储空间
- 便于使用范围查询(BETWEEN...AND),且效率更高
通常,在保存IPv4地址时,一个IPv4最小需要7个字符,最大需要15个字符,所以,使用VARCHAR(15)即可。MySQL在保存变长的字符串时,还需要额外的一个字节来保存此字符串的长度。而如果使用无符号整数来存储,只需要4个字节即可。
另外还可以使用4个字段分别存储IPv4中的各部分,但是通常这不管是存储空间和查询效率应该都不是很高(可能有的场景适合使用这种方式存储)。
使用字符串和无符号整数来存储IP的具体性能分析及benchmark,可以看这篇文章。
https://bafford.com/2009/03/09/mysql-performance-benefits-of-storing-integer-ip-addresses/
使用无符号整数来存储也有缺点:
- 不便于阅读
- 需要手动转换
对于转换来说,MySQL提供了相应的函数来把字符串格式的IP转换成整数INET_ATON,以及把整数格式的IP转换成字符串的INET_NTOA。如下所示:
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)
对于IPv6来说,使用VARBINARY同样可获得相同的好处,同时MySQL也提供了相应的转换函数,即INET6_ATON和INET6_NTOA。
对于转换字符串IPv4和数值类型,可以放在应用层,下面是使用java代码来对二者转换:
package com.mikan;/**
* @author Mikan
*/
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"));
}
}
输出结果为:
3232235521192.168 .0 .1
167772161
边栏推荐
猜你喜欢

pytest框架之fixture测试夹具详解

WeChat applet--" applet global configuration and detailed explanation pull-down refresh and pull-up bottom page events

VoLTE Basic Self-Learning Series | VoLTE Network Architecture

VoLTE Basic Self-Learning Series | IMS Network Overview

lottie-web,lottie动画使用详解

servlet 教程 1:环境搭建和新建 servlet 项目

图论与网络模型——基于R

何为“天道”?

This beta version of Typora is expired

QGIS最受欢迎的20个插件
随机推荐
LeetCode 剑指 Offer 24. 反转链表
WeChat applet--" applet global configuration and detailed explanation pull-down refresh and pull-up bottom page events
Codeforces Summer Training Weekly Report (7.28~8.3)
NIO learning
路由交换综合实验
为什么NIO比BIO效率高
ASEMI整流桥GBL610参数,GBL610尺寸,GBL610特征
2022A特种设备相关管理(电梯)特种作业证考试题库模拟考试平台操作
LeetCode 剑指 Offer 06. 从尾到头打印链表
Swordsman Offer II 091. Paint the House
【n子棋】
2022A Special equipment related management (elevator) special work permit test question bank simulation test platform operation
Scrapy抓取知乎网站
VoLTE Basic Self-Learning Series | The relationship between IMS, VOIP, VoLTE, and RCS?
VoLTE基础自学系列 | VoLTE终端哪些场景会触发CSFB?
#region 与 #endregion 用法(注释代码的折叠)
VoLTE基础自学系列 | IMS网络概述
Detailed explanation of fixture test fixture of pytest framework
js 几种继承的方式
servlet tutorial 1: environment setup and new servlet project