千万不要再用varchar类型来存ip地址了!

对于一个ip地址,比如“192.168.0.110”,由于存在“.”号,所以大部分人都会用varchar类型的字段来进行存储,但是大家有没有想过,对于这样一个字符串,每个字符占用一个字节,那么就需要占用13个字节,但如果能用int存的话,就只需要占用4个字节。

有必要吗?

有人可能会说,不就差几个字节而已嘛,有必要吗?况且你如何用int类型来存ip地址呢?

首先我先回答第一个问题,我最近在研究MySQL的源码,深刻体会到了MySQL源码中对占用字节的“省吃俭用”,MySQL的本质是把数据存到磁盘并取出来用,因此相同的空间内比如16KB,如果存的有效数据越多,那么MySQL的读写性能就会越高,比如同样20个字节,就只能存1个varchar类型的ip地址,但是能存5个int类型的ip地址。

同时我也在重温《高性能MySQL》,其中有一句话我非常赞同:我们应该将更多的时间花在schema优化、索引和查询设计上。

大家往往会重视索引的设计,但忽视了schema的设计。

如何用int类型来存ip地址

再来看第二个问题,如何用int类型来存ip地址呢?

其实答案在MySQL官网中就提到了,MySQL提供了两个函数:INET_ATON()和INET_NTOA()。

INET_ATON()用来把一个ip地址字符串转成数字,比如


INET_NTOA()则相反,用来把一个数字转成ip地址字符串,比如

因此,如果我们在定义字段时,可以这么定义ip字段:

CREATE TABLE t (
  id int auto_increment primary key,
  ip int unsigned
);

注意,必须用int unsigned,这样能支持的数字范围上限更大,如果用的int signed,则可能会导致某些ip地址转成的数字超过了上限无法存储,无符号整型比有符号整型能表示的数字上限更大

数据库不兼容怎么办?

有人可能会想到,那难道在SQL语句中直接用INET_ATON()和INET_NTOA()这两个函数吗,其他数据库不兼容怎么办?

没关系,我们可以用Hutool中的Ipv4Util,它提供了类似的两个方法,并且实现逻辑和MySQL中的两个函数是一致的

底层算法

当然,如果你想自定义两个方法来完成这件事情,也不难,INET_ATON()的实现逻辑为:

  1. 按"."号切分ip地址字符串为4个部分
  2. 110乘以256的0次方
  3. 0乘以256的1次方
  4. 168乘以256的2次方
  5. 192乘以256的3次方
  6. 以上4个结果相加既得到最终结果

总结

要想数据库的性能高,除开配置、除开索引,不要忽略了字段类型的设计,合理的字段类型设计能达到四两拨千斤的效果。

我是大都督周瑜,最近在研究MySQL源码,并用Java手写了一个MySQL,可以关注我的公众号:IT周瑜,或直接加我微信:dadudu6789

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值