Mysql 数字类型|小册免费学

236 阅读2分钟

本篇主要是记录一下平时遇到的数字类型使用的问题

数字类型

类型占用空间最小值~最大值
Tinyint1-128~127
Smallint2-32768~32767
Mediumint3-2²³ ~ 2²³-1
int4-2³¹ ~ 2³¹-1
Bigint8-2⁶³ ~ 2⁶³-1

这里可能要注意一下:signedunsigned 的区别。默认是 signed,而且在使用中也不建议使用 unsigned。因为你在减的过程中可能为负数,这个就超出了 unsigned 的表示范围,就会出现:BIGINT UNSIGNED value is out of range in 这个错误:

可以通过 NO_UNSIGNED_SUBTRACTION

SET sql_mode='NO_UNSIGNED_SUBTRACTION';

允许相减的结果为 signed,这样相减就对了。

浮点数和高精度

  • Float
  • DECIMAL(M,N)

对于 DECIMAL(M,N) 需要注意的是:

  1. M 是保存值的位数,也就是整个有多少位
  2. N 才是标志小数点后保存的位数

同时在金融字段里面,不推荐使用 DECIMAL ,更推荐使用 BIGINT 。为什么呢?

  1. DECIMAL 实现是用二进制实现,不如 整型 来的高效
  2. 同时 DECIMAL 是一个变长字段,这个在存储行上会多余分配一个变长空间
  3. 在更新时,需要额外分配空间,造成碎片,同时和2结合

至于 float 这种浮点的,那就更不可能高精度了,这个存储本身就不真实,所以完全不建议在生产环境使用。

关于自增

直接说怎么做:

  1. BIGINT 做主键
  2. 自增值并不持久化,建议升级到 8 以后

先说第一个:

一个类型能不能满足业务,先看他的表示范围,最大到 42亿,但是互联网的数据谁知道呢,很容易就超过这个表达限制,所以干脆直接升到 BIGINT

第二个是什么呢?

可能很疑惑,为什么自增还要持久化,mysql 不就是持久化嘛?简单来说,AUTO_INCREMENT 其实在每一次重新启动的时候,读取当前表最大的id,作为 AUTO_INCREMENT 的启动值,并存储在内存中,但是以下情况:

  • 删除一条
  • 并发插入时就会造成主键Id不连续

8之后 AUTO_INCREMENT 的变化会写入到 redo log 里面,所以出现问题或者是重启都可以从 redo log 中恢复,避免出现不单调的主键。