Int(4)和Int(11) 你选的是哪个?

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: Int(4)和Int(11) 你选的是哪个?

缘起

大家平时在进行数据库设计的时候,如果遇到需要存储整数类型的数据的时候,通常会优先使用Int这个整数类型,在处理20亿级别的正负数值存储上,Int类型是完全能够满足日常需求的了。


但是在进行数据库建表语句书写的时候,大家经常会见到Int类型的后面会带上1个括号,里面跟上1个数值,通常要么是4,要么是11。如下:image.png这 int 括号里面的数值,究竟是什么意思呢?有的开发者认为,这个数值是用来限制Int类型能够存储的数字的长度的( 类似char、varchar括号数值 );有的开发者则认为,在存储相同数字的情况下,Int(4)会比Int(11)在存储上节省更多的存储空间。


那么实际情况究竟是怎样的呢?在实际的数据库设计中,究竟应该使用Int(4)还是Int(11)呢?又或者是应该什么都不写,只用默认的Int呢?


让我们开启今天的MySQL数据库之Int类型之旅。^_^

存储比较

为了方便测试Int(4)、Int(11)、以及默认的Int,在存储上是否存在差别,我们分别创建t_int_four、t_int_eleven、t_int_default表,如下:image.png接下来,我们向t_int_four表的my_int_four字段,插入Int( 有符号 )类型的最大值2147483647,如下:

image.png如上图,我们看到m_int_four字段的Int(4)类型,并没有影响到Int类型最大值2147483647的插入。可见这个Int括号中的数值4,并不是对数字长度的存储进行限制的,也就是说,只要不超过Int( 有符号 )类型的最小值和最大值的范围,都是可以正确存储的。


接下来我们向t_int_eleven表的my_int_eleven字段,插入Int类型的最大值2147483647。如下:

image.png如上图,我们看到,my_int_eleven字段的Int(11),也成功存储了Int类型的最大值2147483647。


接下来我们向t_int_default表的my_int_default字段,插入Int类型的最大值。如下:

image.png如上图,my_int_default字段的Int类型,也成功存储了Int类型的最大值。这也就进一步证明了,Int类型括号中的数值,对该列字段的数值的存储长度是没有任何影响的,只要不超出Int类型的数值范围,都是可以被正确存储的。


这里我们发现Int类型的最大值2147483647,是一个10位长度的数字,那么my_int_eleven字段的Int(11),能否突破Int类型的最大值,存储11位长度的数值呢?


我们存入一个11位的数字,如下:image.png如上图,这里我们发现,即便设置了Int(11)的列字段,依然无法突破Int类型的数值范围存储限制,最终还是只允许存储Int( 有符号 )类型的有效数值范围。


那么Int(4)、Int(11)、以及默认的Int,在存储空间的占用上是否存在差别呢?是否相同位数长度的数值,Int(4)就比Int(11)节省更多的物理存储空间呢?


接下来,我们打开磁盘上的表t_int_four、t_int_eleven、t_int_default这3个表的表空间文件( 后缀名是.ibd ),打开进行对比,如下:image.pngimage.pngimage.png从上图的元数据中,我们看到不管是t_int_four的Int(4),还是t_int_eleven的Int(11),甚至是t_int_default的Int,在存储空间占用上,都是用了4个字节的空间大小,这里的FF FF FF FF,就是我们所存储的Int类型的最大值2147483647,如下:image.png由于我们的Int类型是有符号的,也就是能存储负数。所以这里的4294967295需要除以2,得到有符号的正数2147483647,就是Int( 有符号 )类型的最大值了。

image.png关于有符号整数的存储及计算方法,大家可以在网上自行查询脑补,这里就不再陈述了。

ZEROFILL

经过上面的示例,我们已经知道Int类型括号中的数值,并不是控制录入数据的数值位数长度的,那么它究竟是用来干什么的呢?


在《MySQL中文参考手册》中,数值类型的列字段,都有一个叫做ZEROFILL的可选属性,如下:image.png按照文档中的介绍,如果一个数值类型的列字段,加上了ZEROFILL的属性后,该列类型会自动变为Unsigned( 无符号 )类型,并具备自动补0的功能。


那么究竟是什么样的效果呢?下面我们看一个示例。image.png如上图,在t_int_zerofill表中,我们分别创建了表示Int(4)、Int(11)、Int的3个字段:my_int_four、my_int_eleven、my_int_default。


我们在插入了1条每个字段值为数字1的数据后,发现查询出来的结果表中,自动在每个Int类型的字段列上,补了数字0。使得每一个数字列中的数值长度,正好等于该列字段Int括号中数值的长度。如下:image.png上面表格中,我们发现,如果Int类型的列字段中,存储的数值的位长度,小于Int括号中的数值( 后面统一叫做ZEROFILL长度 ),MySQL在查询显示的时候,就会自动在该列的存储数值的左边,进行补0。使得整个显示值的总长度,等于Int列类型的ZEROFILL长度。


如果使用的是Int默认类型,则按照Int( 无符号 )类型存储的最大数值的位长度进行补0,这里Int( 无符号 )类型的最大值为4294967295,也就是10位。所以my_int_default在显示数字1时,补9位0+1位数字(1),正好是10位。


接下来,我们插入1条各字段数值为1234的数据,如下:image.png如上图,这里我们看到,在插入1234之后,my_int_four的Int(4),就没有再进行补0了,因为数字1234的位长度,正好等于my_int_four列字段的ZEROFILL长度,也就是Int(4)。而其它列my_int_eleven和my_int_default,依然按照各自的ZEROFILL长度进行补0显示。

混合示例

经过上面的示例,我们知道Int类型的ZEROFILL长度参数的用法,那么其他的数值类型,是否也同样使用ZEROFILL长度参数的用法规则呢?


我们创建t_int_complex_zerofill表,并设置不同的数值类型的列字段,如下:image.png如上图,各种数值类型的ZEROFILL长度参数,依然对数值列类型本身的存储大小,是没有影响的。


接下来我们插入1条,各列字段数值为1的测试数据,如下:

image.png如上图,各种数字类型的ZEROFILL长度参数都起到了预期的补0作用。

总结

本篇主要针对MySQL数据库设计中,Int类型的列字段中,括号中不同补0长度的数值设置,以及其他具备相似特性的数值列类型,进行对了对比和分析。


经过不同的示例分析,我们知道了数值列类型的补0长度的数值设置,也就是ZEROFILL的长度参数设置,对数值列类型本身的存储是没有任何影响的。


在数值列类型的字段上,如果没有显示声明“ZEROFILL”标识的话,只要存储的数值不超过该数字列类型( 有符号 )的数值范围,就都可以正确存储。也就是说Int(4)和Int(11)在存储大小上,是没有任何差别和限制的。


数值列类型的补0长度的数值设置,只有在该数值列类型的字段上,显示声明“ZEROFILL”标识之后,才会按照数值列类型的补0长度( ZEROFILL长度参数 ),进行补0显示。


那么为什么在很多MySQL的建表语句中,会经常见到没有ZEROFILL标识的Int(4)和Int(11)的写法呢?


阿K认为,这里可能主要有2种方向的考虑。

  • Int(11):因为Int( 有符号 )类型的最大数值为2147483647,位长度是10。那么在存储的时候,就能从括号中看出来,在进行数据插入的时候,就不要输入11位长度的数字,比如:12345678901,就是超出范围的非法数据。用作数字插入的预警作用。
  • Int(4):因为Int列类型的存储空间大小为4字节,在设计和存储的时候,就能够从括号中看出来Int列类型的占用空间大小,从而结合char、varchar等其它列的类型,方便的计算出来每条数据在插入的时候,所占用存储空间的大小,从而帮助开发者进行存储优化和数据库表优化。比如上面的t_int_complex_zerofill示例表,

image.png我们很容易就能从各个数值列字段的ZEROFILL长度中,累加计算出,每向表中增加1条数据,就会用掉18个字节的存储空间,公式如下:

TINYINT(1) + SMALLINT(2) + MEDIUMINT(3) + INT(4) + BIGINT(8) = 18字节


在实际的数据库设计开发中,每位设计者的观点和想法都不尽相同,都有自己的设计考量。关于Int数值类型的字段设计,究竟Int(4)和Int(11)谁更好更美呢?作为开发人员的您,又是怎么看待它们的呢?

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
算法 C# C++
for (int i = 0; i < v.size() - 1; i++)
for (int i = 0; i < v.size() - 1; i++)
int和long类型
int和long类型
262 0
|
编译器 C语言 C++
C/C++中int128的那点事
C/C++中int128的那点事
435 0
C/C++中int128的那点事
(*void(*)())0)()和void(*signal(int, void(*)(int)))(int); 讲解
(*void(*)())0)()和void(*signal(int, void(*)(int)))(int); 讲解
105 0
|
C语言 C++
C++中int int& int * int**的区别、联系和用途
C++中int int& int * int**的区别、联系和用途
355 0
C++中int int& int * int**的区别、联系和用途
int(*p)[4] int*p[4]
int(*p)[4] int*p[4]
256 0
int 与 unsigned int
cpp primer  P31 带符号类型和不带符号类型   1、除去布尔型和扩展字符外,其他整型可以划分为带符号的(signed)和无符号的(unsigned)两种。
1113 0
*(int*)&p
Look at following code: void func() { // ... } int main() { void (*p)(); *(int*)&p = (int)func; (*p)(); return 0; } 分析: void(p)(); 这行代码定义了一个指针变量p,p指向一个函数。
1278 0