在进行表结构设计时,数字类型是最常见的类型之一,但数字类型不一定简单。
tinyint(1)
和 tinyint(3) 有什么区别吗?int类型作为数据表主键是否合理?有什么风险?
微信支付以及支付宝的表示金额的为什么要使用分为基础单位?
带着这几个问题,让我们一起思考什么是最佳实践吧。
数字类型之整形
MySQL数据库支持的整形:
tinyint smallint mediumint int bigint
取值范围
| 类型 | 占用空间(Byte) | 位 | 最小值 , 最大值(signed) | 最小值 , 最大值(unsigned) |
|---|---|---|---|---|
| tinyint | 1 | 8 | -2^7 , 2^7 -1 | 0 , 2^8-1 |
| smallint | 2 | 16 | -2^15 , 2^15-1 | 0 , 2^16-1 |
| mediumint | 3 | 24 | -2^23 , 2^23 -1 | 0 , 2^24-1 |
| int | 4 | 32 | -2^31 , 2^31 -1 | 0 , 2^32-1 |
| bigint | 8 | 64 | -2^63 , 2^63 -1 | 0 , 2^64-1 |
常用的类型可能就 tinyint 、int 、bigint。
tinyint类型,占用空间1字节,在 signed 情况下,为 (-2^7,2^7-1),即 -128,127。
这里为什么不是 -2^7? 这里要说明一下,在数据类型中,有 signed 和 unsigned属性,在 signed的情况下,数据库需要分配一位去存储数值的正负号。
2^7 - 1,是为什么呢?这是因为 0 的原因。
那么tinyint(1) 和 tinyint(3)有什么区别呢?
这里没什么区别。不论是 tinyint(1)还是 tinyint(3),在 signed情况下,存储的数字最大值都是 127!
有一种说法是:跟 填充零有关系,目前没测试出来。
ps:
在实际工作过程中,设置 长度,也仅仅是提示说明。
在设计数据表的时候,需要考虑好是否要使用unsigned,但是当查询时,有使用运算的情况,对应字段如果出现负数,会引发MySQL的报错:计算结果超出范围,这时候需要修改 sql_mode 的值 为 NO_UNSIGNED_SUBTRACTION,允许计算结果为 signed。
数字类型之浮点型
MySQL 的浮点型为 float 和 double 类型。但是因为这些类型不是高精度,并且从 MySQL 8.0.17 开始,当设置 float 和 double 时,会提示将在以后的版本废弃浮点类型。
数字类型之高精度型
MySQL 的高精度型为 decimal类型,声明该类型必须要指定精度和标度。通常用户表示账户余额等业务。
amount decimal(2,2)
其中,2表示精度,指扣除小数点后的数字数。2表示小数点后的位数。如下:
0.12 // 可存储
2.2 可存储
11 可存储
3.23 // 提示超出范围
最佳实践
1、int 作为数据表主键时,自增设计
我们在设计表时,可能喜欢用 id + auto_increment ,以实现自增功能。但是,有一点要注意的是,int的范围最大在 42亿的级别,如果你的真实业务量比较大,比如千万级的,可能用不了多久就会到上限,可以考虑使用 bigint。
2、当int到上限时,会发生什么?
当int到达上限后,再次进行自增插入,会提示重复错误 。
3、自增容易被撞数据,需要设置好权限验证。
例如:http://www.test.com/user/1 以及 http://www.test.com/user/2
3、资金字段的设计
在设计用户余额、钱包之类的业务设计中,由于都是资金字段,通常程序员喜欢用 decimal 元单位存储,在业界更佳实践是用分单位,在数据库中用100表示,对接过三方支付接口的人,能明显的发现无论是微信支付还是支付宝,都是用的分单位。
另外,在PHP对含有小数点的数据,判断相等或者其他操作的时候,需要小心。
在前端显示,做好显示转换即可
原因如下:
decimal是通过二进制实现的一种编码方式,计算效率不如整形高效。
使用分存储,int可以 4200万级别的金额。bigint更能存储千兆级别的金额。
定长存储,存储更紧凑,性能更好,减少碎片空间的出现。
对于基础不好的同学,建议报姜承尧老师在拉勾教育开的新课《姜承尧的MySQL实战宝典》,我也正在学,补补自己的短板。
姜承尧,是MySQL DBA界的老前辈,目前供职于腾讯,任金融数据平台与研发中心总监。
在久游开启了数据库职业生涯,接着在网易负责数据库内核、云数据库开发,现在腾讯负责金融支付系统的数据库开发。
这些年先后出版过 《MySQL技术内幕》《MySQL内核》 系列三本书,但相对理论,每本书的方向都较为专一,未能有效地从整个业务的全链路角度去分享一个互联网海量 MySQL 架构的实现。
跟我一起学习:

或者,选择学全场:

谢谢,下期再见~




