当前位置: 首页 > 科技观察

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

时间:2023-03-11 23:10:08 科技观察

原因是平时设计数据库的时候,如果需要存储整数类型的数据,通常会优先使用整数类型Int。在处理20亿级别的正负值存储时,Int类型完全可以满足日常需求。但是,在写建表语句的时候,经常会看到Int类型后面跟着一个小括号,后面跟着一个值,一般不是4就是11。如下: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表,如下:接下来,我们在t_int_four表的my_int_four字段中,插入Int(signed)类型的最大值,2147483647,如下:如上图所示,我们可以看到m_int_four字段的Int(4)类型确实不影响插入Int类型的最大值,2147483647。可以看出这个Int括号中的值4不限制数字长度的存储,即只要不超出Int(有符号)类型的最小值和最大值的范围,就可以正确存储。接下来,我们将Int类型的最大值2147483647插入到t_int_eleven表的my_int_eleven字段中。如下:如上图所示,我们可以看到my_int_eleven字段的Int(11)也成功存储了Int类型的最大值,2147483647,接下来我们将Int类型的最大值插入到my_int_default中t_int_default表的字段。如下:如上图所示,my_int_default字段的Int类型也成功存储了Int类型的最大值。这进一步证明,Int类型括号内的值对列字段的值的存储长度没有影响,只要不超过Int类型的取值范围,就可以正确存储。这里我们发现Int类型的最大值是2147483647,这是一个10位数字,那么my_int_eleven字段中的Int(11)是否可以突破Int类型的最大值,存储一个11位的值呢?我们存储一个11位的值数字如下:如上图所示,这里我们发现即使设置了Int(11)的列字段,仍然无法突破其取值范围的存储限制Int类型,最后只允许存储Int(有符号)类型的有效值范围。那么Int(4),Int(11),和默认的Int,占用的存储空间有什么区别吗?同样位长的值,Int(4)是否比Int(11)节省更多的物理空间呢?存储空间呢?接下来,我们打开磁盘上t_int_four、t_int_eleven、t_int_default这三个表的表空间文件(后缀名为.ibd),打开对比,如下:从上图中的元数据可以看出不管是t_int_four的Int(4),还是t_int_eleven的Int(11),甚至是t_int_default的Int,在存储空间上,都是用了4个字节的空间。这里,FFFFFFFF就是我们存储的Int类型的最大值是2147483647,如下:由于我们的Int类型是有符号的,所以可以存储负数。所以这里的4294967295需要除以2得到有符号正数2147483647,也就是Int(有符号)类型的最大值。关于有符号整数的存储和计算方法,大家可以上网查脑补,这里不再赘述。ZEROFILL经过上面的例子,我们已经知道Int类型括号中的值并不能控制输入数据的数字位数的长度,那么它是用来做什么的呢?在《MySQL中文参考手册》中,数值类型的列字段,有一个可选属性ZEROFILL,如下:根据文档中的介绍,如果一个数值类型的列字段添加了ZEROFILL属性,则该列类型会自动变成Unsigned(无符号)类型,并具有Automaticallyadd0功能。那么具体效果如何呢?我们来看一个例子。如上图,在t_int_zerofill表中,我们创建了三个分别代表Int(4)、Int(11)和Int的字段:my_int_four、my_int_eleven和my_int_default。插入一条每个字段值为1的数据后,我们发现在查询结果表中,每个Int类型的字段列自动添加了0。使每个数字列中的值的长度恰好等于列字段Int中括号中的值的长度。如下:在上表中,我们发现如果Int类型列字段中存储的值的位长小于Int括号中的值(以下简称ZEROFILL长度),MySQL会自动显示在查询中。列中存储的值的左侧填充0。使整个显示值的总长度等于Int列类型的ZEROFILL长度。如果使用默认类型Int,则根据Int(unsigned)类型存储的最大值的位长补0,其中Int(unsigned)类型的最大值为4294967295,即10位。所以my_int_default显示数字1时,补9位0+1位(1),正好是10位。接下来,我们在每个字段中插入一条值为1234的数据,如下:如上图所示,这里可以看到插入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表,设置不同数值类型的列字段,如下:接下来插入一段测试数据,为每个列字段设置数值列类型的无符号最大值,如下:上图中,各种数值类型的ZEROFILL长度参数仍然是针对数值列类型本身的存储大小不受影响。接下来我们插入1条各列字段值为1的测试数据,如下:如上图所示,各种数字类型的ZEROFILL长度参数起到了预期的补0作用。总结本文主要对比分析MySQL数据库设计中Int类型列字段括号内不同补0长度的数值设置,以及其他具有类似特性的数值列类型。通过分析不同的例子,我们知道数值列类型的0填充长度的值设置,即ZEROFILL的长度参数设置,对数值列类型本身的存储没有影响。在数值列类型的字段上,如果不显示“ZEROFILL”标志,只要存储的值不超过数值列类型(有符号)的取值范围,就可以正确存储。也就是说,Int(4)和Int(11)在存储大小上没有区别和限制。对于数值列类型的补0长度的取值设置,只有在数值列类型的字段上显示并声明了“ZEROFILL”标志后,才会根据补0进行补0显示数字列类型的长度(ZEROFILL长度参数)。那么为什么在很多MySQL建表语句中经常看到没有ZEROFILL标志的Int(4)和Int(11)呢?AK认为,这里可能主要有两方面的考虑。Int(11):因为Int(signed)类型的最大值是2147483647,所以位长是10。那么在存储的时候,从括号中可以看出,在插入数据的时候,不要输入长度为11的数字,如:12345678901,是超出范围的非法数据。用作数字插入的早期警告。Int(4):因为Int列类型的存储空间是4个字节,所以在设计和存储的时候,可以从括号中看出Int列类型占用的空间,从而结合char、varchar等列类型,方便计算每条数据插入时占用的存储空间大小,帮助开发者优化存储和数据库表。例如,在上面的t_int_complex_zerofill示例表中,我们可以很容易地从每个数字列字段的ZEROFILL长度累加和计算。每增加一条数据到表中,就会占用18字节的存储空间。公式如下:TINYINT(1)+SMALLINT(2)+MEDIUMINT(3)+INT(4)+BIGINT(8)=18bytes有自己的设计考虑。关于Int数值类型的字段设计,Int(4)和Int(11)谁更好更漂亮?作为开发人员,您如何看待他们?