为何数据库推荐将IPv4地址存储为32位整数而非字符串?

目录

一、IPv4地址在数据库中的存储方式?

二、IPv4地址的存储方式比较

(一)字符串存储 vs 整数存储

(二)IPv4地址"192.168.1.8"说明

三、数据库推荐32位整数存储方式原理

四、存储方式对系统性能的影响

(一)数据准备

(二)查询效率比较

(三)索引性能比较

五、应用层IP转换操作

六、总结


干货分享,感谢您的阅读!

在这个互联网高速发展的时代,IP地址就像每一个网站的身份证,帮助我们在浩瀚的网络海洋中找到方向。但你是否想过,这些数字串究竟是如何被存储的?想象一下,如果把你的家地址写成一串长长的数字,或者把它变成一个32位的整数,这听起来像是科学家在做数学实验,但其实,这却是程序员们为提升数据库性能而进行的“魔法”。

就像在一家餐馆点菜,你可以选择一份诱人的意面(字符串存储),看起来色香味俱全,但吃完后发现胃部撑得慌;或者选择一份精简的沙拉(整数存储),虽然简单但却让你轻松自在,身心舒畅。那么,究竟哪个选择更胜一筹呢?在接下来的内容中,我们将一探究竟,揭秘IP地址存储的“幕后故事”,让你不再是一个无知的网络游民,而是一位懂得选择的智者!准备好了吗?让我们一起踏上这段探索之旅吧!

一、IPv4地址在数据库中的存储方式?

在Java开发过程中,我们通常会使用数据库来存储各种类型的数据,包括IPv4地址。但是,我们应该如何存储这些IP地址才能最大程度地提高系统的性能呢?使用字符串存储IPv4地址可能会更直观,但是否是最佳选择呢?

究竟应该如何存储IPv4地址才能最大程度地提高数据库的性能和系统的效率呢?我们进行探讨下为何数据库推荐将IPv4地址存储为32位整数而非字符串,并从Java开发者的角度分析这种存储方式对系统性能和开发流程的影响。

二、IPv4地址的存储方式比较

(一)字符串存储 vs 整数存储

存储方式优点缺点
字符串存储

直观性:更易于人类理解和查看

灵活性:可以存储不同格式的IPv4地址

存储空间消耗大:每个IPv4地址需要较大的存储空间

效率低下:字符串比较通常耗时较长

难以进行数学运算和比较:需要额外的格式转换和解析

整数存储

存储空间效率高:只需较小存储空间

查询效率高:整数比较速度更快,索引和查询效率更高

数学运算方便:可以直接进行数学运算和比较

可能丢失部分信息:无法存储IPv6地址等其他地址格式

不直观:整数表示的IPv4地址不易于人类理解和查看

(二)IPv4地址"192.168.1.8"说明

当我们将IPv4地址"192.168.1.8"存储为字符串时,以十进制格式显示,类似于我们平时在浏览器中看到的网址,这种表示方法直观而易读。但一般每个IPv4地址都需要15个字符的存储空间(包括3个"."分隔符和4个三位数的表示),当数据量大的时候可能会导致:存储空间的浪费+查询和索引时效率降低。因为数据库系统在处理字符串比较时,需要逐字符比较,这可能会增加查询时间。

当我们将IPv4地址存储为32位整数时,它们会以二进制格式表示,例如:3232235776。这种表示方法可能不太直观,但整数只需要4字节的存储空间,远远小于使用字符串存储所需的空间。这意味着在存储大量IPv4地址时,整数存储方式可以显著节省存储空间,还可以提高数据库查询和索引的效率。因为整数比较速度更快,数据库可以更快地执行查询操作,并且可以更有效地利用索引。

因此,虽然字符串存储方式可能更直观和易读,但整数存储方式在存储空间效率和查询效率方面更具优势,这就是为什么数据库通常推荐将IPv4地址存储为32位整数而不是字符串的原因。

三、数据库推荐32位整数存储方式原理

整数存储IPv4地址的原理非常简单,它是基于IPv4地址的32位二进制表示的。IPv4地址由四个8位组成,每个组都可以表示为一个0到255的十进制数,或者一个0x00到0xFF的十六进制数。因此,将IPv4地址存储为32位整数实际上是将这四个8位的组合表示为一个32位的二进制数。

具体来说,如果将IPv4地址 "192.168.1.8" 转换为32位整数的表示,可以将每个IPv4地址的部分转换为二进制形式。

对于 "192.168.1.8",分别转换为二进制:

  • 192 -> 11000000
  • 168 -> 10101000
  • 1 -> 00000001
  • 8 -> 00001000

将这四个二进制数按顺序连接起来(11000000101010000000000100001000),形成一个32位的二进制数。最后,将这个32位的二进制数转换为整数,即为 IPv4 地址 "192.168.1.8" 对应的32位整数。转换后的整数值是:3232235776(以十进制表示)。

四、存储方式对系统性能的影响

(一)数据准备

使用数据库管理工具(如MySQL Workbench、phpMyAdmin等)或者命令行工具(如MySQL的命令行客户端)连接到数据库服务器。

在数据库zyf中创建新表,用于存储IPv4地址,选择将IPv4地址存储为字符串类型或整数类型:

  • 如果选择字符串类型,可以使用VARCHAR
  • 如果选择整数类型,可以使用INT

具体如下:

-- 创建表,将IPv4地址存储为字符串
CREATE TABLE ip_addresses_string (id INT AUTO_INCREMENT PRIMARY KEY,ip_address VARCHAR(15)
);-- 创建表,将IPv4地址存储为整数
CREATE TABLE ip_addresses_integer (id INT AUTO_INCREMENT PRIMARY KEY,ip_address INT UNSIGNED
);

接着我们生成大量的IPv4地址数据。可以考虑使用随机生成器来生成一系列随机的IPv4地址,以模拟真实环境中的数据。分别向 ip_addresses_stringip_addresses_integer 表中插入生成的IPv4地址数据。具体代码如下:

package org.zyf.javabasic.ipaddresses;import java.util.Random;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;/*** @program: zyfboot-javabasic* @description: 简单的Java程序示例,用于生成大量IPv4地址数据并插入到数据库表中* @author: zhangyanfeng* @create: 2024-05-02 23:29**/
public class IPAddressDataGenerator {public static void main(String[] args) {// 数据库连接信息String url = "jdbc:mysql://localhost:3306/zyf";String username = "root";String password = "Zyf2014";// 生成大量IPv4地址数据int numAddresses = 10000; // 要生成的IPv4地址数量String[] ipAddresses = generateIPv4Addresses(numAddresses);// 将数据插入到数据库表中insertData(url, username, password, ipAddresses);}// 生成大量IPv4地址数据private static String[] generateIPv4Addresses(int numAddresses) {String[] ipAddresses = new String[numAddresses];Random rand = new Random();for (int i = 0; i < numAddresses; i++) {// 生成随机的IPv4地址String ipAddress = rand.nextInt(256) + "." + rand.nextInt(256) + "." + rand.nextInt(256) + "." + rand.nextInt(256);ipAddresses[i] = ipAddress;}return ipAddresses;}// 将数据插入到数据库表中private static void insertData(String url, String username, String password, String[] ipAddresses) {try (Connection connection = DriverManager.getConnection(url, username, password)) {// 插入字符串存储的IPv4地址数据insertIPv4Addresses(connection, "ip_addresses_string", ipAddresses);// 将IPv4地址转换为整数存储并插入数据long[] integerAddresses = convertToInteger(ipAddresses);insertIntegerAddresses(connection, "ip_addresses_integer", integerAddresses);} catch (SQLException e) {e.printStackTrace();}}// 插入字符串存储的IPv4地址数据private static void insertIPv4Addresses(Connection connection, String tableName, String[] ipAddresses) throws SQLException {String sql = "INSERT INTO " + tableName + " (ip_address) VALUES (?)";try (PreparedStatement statement = connection.prepareStatement(sql)) {for (String ipAddress : ipAddresses) {statement.setString(1, ipAddress);statement.addBatch();}statement.executeBatch();}}// 将IPv4地址转换为整数存储并插入数据private static void insertIntegerAddresses(Connection connection, String tableName, long[] integerAddresses) throws SQLException {String sql = "INSERT INTO " + tableName + " (ip_address) VALUES (?)";try (PreparedStatement statement = connection.prepareStatement(sql)) {for (long ipAddress : integerAddresses) {statement.setLong(1, ipAddress);statement.addBatch();}statement.executeBatch();}}// 将IPv4地址转换为整数存储private static long[] convertToInteger(String[] ipAddresses) {long[] integerAddresses = new long[ipAddresses.length];for (int i = 0; i < ipAddresses.length; i++) {String[] parts = ipAddresses[i].split("\\.");long ipAddress = 0;for (int j = 0; j < 4; j++) {ipAddress += Long.parseLong(parts[j]) << (24 - (8 * j));}integerAddresses[i] = ipAddress;}return integerAddresses;}
}

(二)查询效率比较

我们对这两种存储方式进行查询,并记录每次查询的时间。最后,我们比较两种存储方式的查询时间,以确定哪种方式的查询效率更高。代码如下:

package org.zyf.javabasic.ipaddresses;import java.sql.*;/*** @program: zyfboot-javabasic* @description: 比较两种存储方式的查询时间,以确定哪种方式的查询效率更高。* @author: zhangyanfeng* @create: 2024-05-02 23:44**/
public class IPAddressStorageComparison {public static void main(String[] args) {// Connect to the databaseConnection connection = null;try {connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zyf", "root", "Zyf2014");// Query IPv4 addresses stored as stringslong startTimeString = System.currentTimeMillis();Statement statement = connection.createStatement();ResultSet resultSetString = statement.executeQuery("SELECT * FROM ip_addresses_string WHERE ip_address = '192.168.1.1'");long endTimeString = System.currentTimeMillis();long durationString = endTimeString - startTimeString;System.out.println("Query time for string storage: " + durationString + " milliseconds");// Query IPv4 addresses stored as integerslong startTimeInteger = System.currentTimeMillis();ResultSet resultSetInteger = statement.executeQuery("SELECT * FROM ip_addresses_integer WHERE ip_address = 3232235777");long endTimeInteger = System.currentTimeMillis();long durationInteger = endTimeInteger - startTimeInteger;System.out.println("Query time for integer storage: " + durationInteger + " milliseconds");// Close the connectionconnection.close();} catch (SQLException e) {e.printStackTrace();}}
}

具体运行如下:

根据查询时间,可以看出整数存储的查询时间明显短于字符串存储的查询时间。整数存储的查询时间为4毫秒,而字符串存储的查询时间为19毫秒。这表明在这次测试中,整数存储的查询效率要比字符串存储的查询效率高。

(三)索引性能比较

在数据库表中分别为IPv4地址字段创建索引,具体如下:

-- 为字符串存储的IPv4地址字段创建索引
CREATE INDEX idx_ip_address_string ON ip_addresses_string (ip_address);-- 为整数存储的IPv4地址字段创建索引
CREATE INDEX idx_ip_address_integer ON ip_addresses_integer (ip_address);

这个时候在运行上面的代码,输出如下:

根据查询时间结果,可以看出整数存储的索引查询时间明显短于字符串存储的索引查询时间,整数存储的索引查询时间为1毫秒,而字符串存储的索引查询时间为10毫秒。这表明在这次测试中,整数存储的索引查询效率要比字符串存储的索引查询效率更高。

五、应用层IP转换操作

提供一个IPUtils 工具类用于IPv4地址和长整型数值之间的相互转换。通过位运算和位掩码,避免了字符串操作和对象创建,提高转换过程的执行效率:

package org.zyf.javabasic.ipaddresses;/*** @program: zyfboot-javabasic* @description: 使用位运算和位掩码来进行IPv4地址和长整型数值的转换* @author: zhangyanfeng* @create: 2024-05-03 00:08**/
public class IPUtils {public static long ipToLong(String ip) {String[] parts = ip.split("\\.");return (Long.parseLong(parts[0]) << 24) +(Long.parseLong(parts[1]) << 16) +(Long.parseLong(parts[2]) << 8) +Long.parseLong(parts[3]);}public static String longToIp(long longIp) {StringBuilder sb = new StringBuilder();sb.append((longIp >>> 24) & 0xFF).append(".");sb.append((longIp >>> 16) & 0xFF).append(".");sb.append((longIp >>> 8) & 0xFF).append(".");sb.append(longIp & 0xFF);return sb.toString();}public static void main(String[] args) {String ip1 = "10.122.28.76";long ip1ToLong = ipToLong(ip1);System.out.println("IPv4地址 \"" + ip1 + "\" 转换为长整型数值的结果是:" + ip1ToLong);String ip2 = "10.168.0.45";long ip2ToLong = ipToLong(ip2);System.out.println("IPv4地址 \"" + ip2 + "\" 转换为长整型数值的结果是:" + ip2ToLong);long longIp = 197958752L;String longIpToIp = longToIp(longIp);System.out.println("长整型数值 \"" + longIp + "\" 转换为IPv4地址的结果是:" + longIpToIp);}
}

六、总结

探讨在Java开发中存储IPv4地址的最佳方式。通过对比字符串存储和整数存储两种方式的优缺点,我们发现整数存储方式在存储空间效率、查询效率和数学运算方面更具优势。虽然字符串存储方式更直观易读,但在处理大量数据时会浪费存储空间并降低查询效率。

通过具体的示例代码演示了如何生成大量的IPv4地址数据,并将其插入到数据库表中。通过查询和索引效率的比较,我们验证了整数存储方式在性能方面的优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474351.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《译文》2024年11月数维杯国际大学生数学建模挑战赛题目

# 赛题正式发布 2024年第十届数维杯国际大学生数学建模挑战赛顺利开赛&#xff0c;竞赛开始时间为北京时间2024年11月15日09:00至北京时间2024年11月19日09:00&#xff0c;共计4天&#xff0c;竞赛题目正式发布&#xff0c;快来一起围观&#xff0c;你认为今年的哪个题目更具有…

机器学习(贝叶斯算法,决策树)

朴素贝叶斯分类 贝叶斯分类理论 假设现有两个数据集&#xff0c;分为两类 我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中红色圆点表示的类别)的概率&#xff0c;用p2(x,y)表示数据点(x,y)属于类别2(图中蓝色三角形表示的类别)的概率&#xff0c;那么对于一个新数据点(x,y)…

【会话文本nlp】对话文本解析库pyconverse使用教程版本报错、模型下载等问题解决超参数调试

前言&#xff1a; 此篇博客用于记录调用pyconverse库解析对话文本时遇到的问题与解决思路&#xff0c;以供大家参考。 文章目录 pycoverse介绍代码github链接问题解决1 [cannot import name ‘cached_download‘ from ‘huggingface_hub‘ 问题解决](https://blog.csdn.net/wei…

5G的SUCI、SUPI、5G-GUTI使用场景及关系

使用场景(来源于对23.501、23.502、33.501、23.003的理解) 1、UE初始注册时&#xff0c;根据HN Public Key把SUPI加密成SUCI&#xff0c;并发送初始注册请求 2、AMF转发SUCI给AUSF和UDM进行认证&#xff0c;并获取解密后的SUPI 3、AMF根据SUPI生成一个5G-GUTI&#xff0c;并保…

2. kafka 生产者

一. 生产者消息发送流程 在消息发送的过程中&#xff0c;涉及到了两个线程&#xff1a;main线程和Sender线程。Producer发送的消息会分别经过Interceptors(拦截器)&#xff0c;Serializer(序列化器)&#xff0c;Partitioner(分区器)最终到达RecordAccumulator&#xff0c;Recor…

web应用安全和信息泄露预防

文章目录 1&#xff1a;spring actuator导致的信息泄露1.1、Endpoint配置启用检测1.2、信息泄露复现1.3、防御 2&#xff1a;服务端口的合理使用3&#xff1a;弱口令&#xff08;密码&#xff09;管理4&#xff1a;服务端攻击4.1、短信业务&#xff0c;文件上传等资源型接口1、…

智慧安防丨以科技之力,筑起防范人贩的铜墙铁壁

近日&#xff0c;贵州省贵阳市中级人民法院对余华英拐卖儿童案做出了一审宣判&#xff0c;判处其死刑&#xff0c;剥夺政治权利终身&#xff0c;并处没收个人全部财产。这一判决不仅彰显了法律的威严&#xff0c;也再次唤起了社会对拐卖儿童犯罪的深切关注。 余华英自1993年至2…

计算机编程中的测试驱动开发(TDD)及其在提高代码质量中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机编程中的测试驱动开发&#xff08;TDD&#xff09;及其在提高代码质量中的应用 计算机编程中的测试驱动开发&#xff08;T…

【MYSQL】锁详解(全局锁、表级锁、行级锁)【快速理解】

目录 一、全局锁 二、表级锁 1.表锁 2.元数据锁 3.意向锁 三、行级锁 1. 行锁 2.间隙锁 3.临建锁 锁是处理并发情况下&#xff0c;对数据的一致性的关键因素&#xff0c;也是并发情况下对效率影响非常大的。 1、全局锁&#xff1a;锁定表中所有数据。 2、表级锁&#xff1a;…

thinkphp6 入门(2)--视图、渲染html页面、赋值

use think\facade\View;View::assign([name > ThinkPHP,email > thinkphpqq.com]);View::assign(data,[name > ThinkPHP,email > thinkphpqq.com]); View::fetch(index);助手函数 view(index, [name > ThinkPHP,email > thinkphpqq.com ]); 模板输出 {$na…

百度智能云 VectorDB 优势数量 TOP 1

近日&#xff0c;IDC 发布了《RAG 与向量数据库市场前景预测》报告&#xff0c;深入剖析了检索增强生成&#xff08;RAG&#xff09;技术和向量数据库市场的发展趋势。报告不仅绘制了 RAG 技术的发展蓝图&#xff0c;还评估了市场上的主要厂商。在这一评估中&#xff0c;百度智…

MySQL索引的底层实现原理是什么?

MySQL索引的底层实现主要基于B树数据结构。B树是一种平衡多路查找树&#xff0c;具有以下特点&#xff1a; 1、树的所有叶子节点都位于同一层&#xff1a; 这确保了从根节点到每个叶子节点的路径长度相同&#xff0c;保证了查询效率的一致性。 2、节点中的数据按键值大小有序…

手搓神经网络(MLP)解决MNIST手写数字识别问题 | 数学推导+代码实现 | 仅用numpy,tensor和torch基本计算 | 含正反向传播数学推导

手写数字识别&#xff08;神经网络入门&#xff09; 文章目录 手写数字识别&#xff08;神经网络入门&#xff09;实验概述实验过程数据准备模型实现线性变换层前向传播反向传播更新参数整体实现 激活函数层&#xff08;ReLU&#xff09;前向传播反向传播整体实现 Softmax层&am…

在MATLAB中导入TXT文件的若干方法

这是一篇关于如何在MATLAB中导入TXT文件的文章&#xff0c;包括示例代码和详细说明 文章目录 在MATLAB中导入TXT文件1. 使用readtable函数导入TXT文件示例代码说明 2. 使用load函数导入TXT文件示例代码说明 3. 使用importdata函数导入TXT文件示例代码说明 4. 自定义导入选项示例…

ks 小程序sig3

前言 搞了app版的快手之后 &#xff08;被风控麻了&#xff09; 于是试下vx小程序版的 抓包调试 小程序抓包问题 网上很多教程&#xff0c; github也有开源的工具代码 自行搜索 因为我们需要调试代码&#xff0c;所以就用了下开源的工具 &#xff08;可以用chrome的F12功能&a…

解决Spring Boot整合Redis时的连接问题

前言 在使用Spring Boot整合Redis的过程中&#xff0c;经常会遇到连接问题&#xff0c;尤其是当Redis服务部署在远程服务器上时。 问题描述 当你尝试连接到Redis服务器时&#xff0c;可能会遇到以下错误&#xff1a; org.springframework.data.redis.connection.PoolExcept…

算法--“汽车加油”问题.

def greedy():n 100 # 汽车满油后可行驶的最大距离d [50, 80, 39, 60, 40, 32] # 加油站的距离k len(d) # 加油站的数量# 检查是否有加油站距离超过汽车的最大行驶距离for dist in d:if dist > n:print(no solution)returnnum 0 # 加油次数current_position 0 # 当…

道陟科技EMB产品开发进展与标准设计的建议|2024电动汽车智能底盘大会

11月12日&#xff0c;2024电动汽车智能底盘大会在重庆开幕。会议由中国汽车工程学会主办&#xff0c;电动汽车产业技术创新战略联盟、中国汽车工程学会智能底盘分会、智能绿色车辆与交通全国重点实验室承办。本届大会围绕电动汽车智能底盘相关技术发展与融合&#xff0c;满足高…

sqli—labs靶场 5-8关 (每日4关练习)持续更新!!!

Less-5 上来先进行查看是否有注入点&#xff0c;判断闭合方式&#xff0c;查询数据列数&#xff0c;用union联合注入查看回显位&#xff0c;发现到这一步的时候&#xff0c;和前四道题不太一样了&#xff0c;竟然没有回显位&#xff1f;&#xff1f;&#xff1f; 我们看一下源…

【qt】控件3

1.setToolTip和setToolTipDuration setToolTip这个函数用来设置提醒内容 setToolTipDuration这个函数用来设置提醒时间 Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->help->setToolTip("按下这个按键就可以提…