设计-Int(4)和Int(11)谁更美
设计-Int(4)和Int(11)谁更美
【缘起】
大家平时在进行数据库设计的时候,如果遇到需要存储整数类型的数据的时候,通常会优先使用Int这个整数类型,在处理20亿级别的正负数值存储上,Int类型是完全能够满足日常需求的了。
但是在进行数据库建表语句书写的时候,大家经常会见到Int类型的后面会带上1个括号,里面跟上1个数值,通常要么是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( 有符号 )类型的最大值2147483647,如下:
如上图,我们看到m_int_four字段的Int(4)类型,并没有影响到Int类型最大值2147483647的插入。可见这个Int括号中的数值4,并不是对数字长度的存储进行限制的,也就是说,只要不超过Int( 有符号 )类型的最小值和最大值的范围,都是可以正确存储的。
接下来我们向t_int_eleven表的my_int_eleven字段,插入Int类型的最大值2147483647。如下:
如上图,我们看到,my_int_eleven字段的Int(11),也成功存储了Int类型的最大值2147483647。
接下来我们向t_int_default表的my_int_default字段,插入Int类型的最大值。如下:
如上图,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这3个表的表空间文件( 后缀名是.ibd ),打开进行对比,如下:
从上图的元数据中,我们看到不管是t_int_four的Int(4),还是t_int_eleven的Int(11),甚至是t_int_default的Int,在存储空间占用上,都是用了4个字节的空间大小,这里的FF FF FF FF,就是我们所存储的Int类型的最大值2147483647,如下:
由于我们的Int类型是有符号的,也就是能存储负数。所以这里的4294967295需要除以2,得到有符号的正数2147483647,就是Int( 有符号 )类型的最大值了。
关于有符号整数的存储及计算方法,大家可以在网上自行查询脑补,这里就不再陈述了。
【ZEROFILL】
经过上面的示例,我们已经知道Int类型括号中的数值,并不是控制录入数据的数值位数长度的,那么它究竟是用来干什么的呢?
在《MySQL中文参考手册》中,数值类型的列字段,都有一个叫做ZEROFILL的可选属性,如下:
按照文档中的介绍,如果一个数值类型的列字段,加上了ZEROFILL的属性后,该列类型会自动变为Unsigned( 无符号 )类型,并具备自动补0的功能。
那么究竟是什么样的效果呢?下面我们看一个示例。
如上图,在t_int_zerofill表中,我们分别创建了表示Int(4)、Int(11)、Int的3个字段:my_int_four、my_int_eleven、my_int_default。
我们在插入了1条每个字段值为数字1的数据后,发现查询出来的结果表中,自动在每个Int类型的字段列上,补了数字0。使得每一个数字列中的数值长度,正好等于该列字段Int括号中数值的长度。如下:
上面表格中,我们发现,如果Int类型的列字段中,存储的数值的位长度,小于Int括号中的数值( 后面统一叫做ZEROFILL长度 ),MySQL在查询显示的时候,就会自动在该列的存储数值的左边,进行补0。使得整个显示值的总长度,等于Int列类型的ZEROFILL长度。如果使用的是Int默认类型,则按照Int( 无符号 )类型存储的最大数值的位长度进行补0,这里Int( 无符号 )类型的最大值为4294967295,也就是10位。所以my_int_default在显示数字1时,补9位0+1位数字(1),正好是10位。
接下来,我们插入1条各字段数值为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表,并设置不同的数值类型的列字段,如下:
接下来,插入1条测试数据,分别为每一个列字段,设置该数值列类型的无符号最大数值,如下:
如上图,各种数值类型的ZEROFILL长度参数,依然对数值列类型本身的存储大小,是没有影响的。
接下来我们插入1条,各列字段数值为1的测试数据,如下:
如上图,各种数字类型的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示例表,
我们很容易就能从各个数值列字段的ZEROFILL长度中,累加计算出,每向表中增加1条数据,就会用掉18个字节的存储空间,公式如下:
TINYINT(1) + SMALLINT(2) + MEDIUMINT(3) + INT(4) + BIGINT(8) = 18字节
在实际的数据库设计开发中,每位设计者的观点和想法都不尽相同,都有自己的设计考量。关于Int数值类型的字段设计,究竟Int(4)和Int(11)谁更好更美呢?作为开发人员的您,又是怎么看待它们的呢?
欢迎留言与阿K进行交流讨论,希望本篇文章对您有所帮助,谢谢!
【示例】
本文中提到的MySQL的示例文件,在阿K的Gitee中都可以找到,如下:
https://gitee.com/Kival/mysql-work-demo
设计-Int(4)和Int(11)谁更美的更多相关文章
- mysql int(3)与int(11)的区别
总结,int(M) zerofill,加上zerofill后M才表现出有点点效果,比如 int(3) zerofill,你插入到数据库里的是10,则实际插入为010,也就是在前面补充加了一个0.如果i ...
- 下面程序的输出结果是____ A:11,10 B:11,11 C:10,10 D:10,11 int x=10; int y=x++; printf("%d,%d",(x++,y),y++);
下面程序的输出结果是____ A:11,10 B:11,11 C:10,10 D:10,11 int x=10; int y=x++; printf("%d,%d",(x++,y) ...
- int(1)和int(11)是否有区别?
MySQL类型关键字后面的括号内指定整数值的显示宽度(例如,INT(11)).该可选显示宽度规定用于显示宽度小于指定的列宽度的值时从左侧填满宽度.显示宽度并不限制可以在列内保存的值的范围,也不限制超过 ...
- int(3)与int(11)的区别
注意:这里的M代表的并不是存储在数据库中的具体的长度,以前总是会误以为int(3)只能存储3个长度的数字,int(11)就会存储11个长度的数字,这是大错特错的.其实当我们在选择使用int的类型的时候 ...
- mysql int(3)与int(11)的区别
总结,int(M) zerofill,加上zerofill后M才表现出有点点效果,比如 int(3) zerofill,你插入到数据库里的是10,则实际插入为010,也就是在前面补充加了一个0.如果i ...
- mysql中int(3)与int(11)有什么区别吗?
注意:这里的M代表的并不是存储在数据库中的具体的长度,以前总是会误以为int(3)只能存储3个长度的数字,int(11)就会存储11个长度的数字,这是大错特错的. 其实当我们在选择使用int的类型的时 ...
- Mysql 中 int(3) 和 int(11) 的区别
[1]int(3) 和 int(11)的区别(思维惯性认知错误) 这里的3或11代表的是存储在数据库中的具体的长度,总以为int(3)只能存储3个长度的数字,int(11)只会存储11个长度的数字. ...
- mysql 数据库中 int(3) 和 int(11) 有区别么???
今天去面试的时候 面试官问到了这个问题:int(3) 和 int(11) 有什么区别?? 当时一听有点蒙,(不知道为什么蒙,后来回来想想可能是觉得考官怎么会问这么简单的问题呢,所以蒙了),当时我的回答 ...
- int(M)与int
int(M) ,加上zerofill后M才表现出有点效果,比如 int(3) zerofill,你插入到数据库里的是10,则实际插入为010,也就是在前面补充加了一个0.如果int(3)和int(10 ...
随机推荐
- 记一次oracle 11g数据导入
1.ORACLE数据库数据导入到测试库环境 172.15.1.51 root kic@test 172.15.1.52 root 一般先将数据导入52的环境(配置比较低),再将数据导入51的环境(本 ...
- 用js刷剑指offer(最小的K个数)
题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 牛客网链接 js代码 function GetLeastNumbe ...
- P3205 [HNOI2010]合唱队[区间dp]
题目描述 为了在即将到来的晚会上有更好的演出效果,作为AAA合唱队负责人的小A需要将合唱队的人根据他们的身高排出一个队形.假定合唱队一共N个人,第i个人的身高为Hi米(1000<=Hi<= ...
- Factorization Machines
- WCF之MSMQ消息队列
一.MSMQ简介 MSMQ(微软消息队列)是Windows操作系统中消息应用程序的基础,是用于创建分布式.松散连接的消息通讯应用程序的开发工具. MSMQ与XML Web Services和.Net ...
- redis-4.0.14 cluster 配置实战
1.操作系统配置 切换到root用户修改配置sysctl.conf vim /etc/sysctl.conf # 添加配置: vm.max_map_count= vm.overcommit_memor ...
- vue tslint报错: Calls to 'console.log' are not allowed
使用Vue CLI 3 的 vue create 创建vue+ts 项目,使用默认配置, 控制台报警告Calls to 'console.log' are not allowed,解决: 在tslin ...
- python 正则表达式特殊字符
字符 描述 \ 将下一个字符标记为一个特殊字符.或一个原义字符.或一个 向后引用.或一个八进制转义符.例如,'n' 匹配字符 "n".'\n' 匹配一个换行符.序列 '\\' 匹配 ...
- 分页器,序列化组件,bulk_create,choices字段
分页器 <!--前端--> {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} ...
- 判断字符串是否是IP地址
#include <stdio.h>#include <string.h> bool isIP(const char* str); int main(){ char str[] ...