整型

TINYINTSMALLINTMEDIUMINTINTBIGINT分别使用了 1,2,3,4,8 字节的存储空间。

UNSIGNED关键字表示不允许插入负数并将正数的取值范围扩大了两倍,但是有符号数和无符号类型的存储空间和性能依旧是一样的。

MySQL 可以指定整型类型的显示宽度,例如INT(11)。显示宽度和数据类型的取值范围是无关的,只是证明了 MySQL 最大可能显示的数字个数。数值的位数小于指定的宽度会由空格填充;如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。

浮点数

FLOATDOUBLE分别为单精度(4 字节)和双精度(8 字节)的浮点数。DECIMAL 是精度可变的定点数,占用的字节由其精度 M 决定。

浮点数和定点数都可以指定精度,例如DECIMAL(11, 5)表示总共 11 位,取 5 位存储小数部分,剩下的 6 位存储整数部分,一种占用了 11+2=13 字节。

CPU 原生支持浮点运算,但不支持对DECIMAL的运算,因此浮点运算会更快。但是浮点数会引起精度问题,像货币这样对精度敏感的数据,在 MySQL 中一般使用DECIMAL(8, 2)来存储。

定点数和浮点数区别

  • 在 MySQL 中,定点数以字符串形式存储,在对精度要求比较高的时候(如货币,科学数据等)使用DECIMAL的类型比较好。
  • 浮点数FLOATDOUBLE相对于定点数DECIMAL的优势是在一定的情况下,浮点数能表示更大的范围数据。
  • 浮点数的减法和比较运算容易产生误差,在使用浮点型需要注意尽量避免浮点数之间的比较。

字符串

MySQL 中主要使用的字符串数据类型有VARCHARCHAR

CHAR是定长串,接收长度固定的字符串。MySQL 总是根据定义的字符串长度分配足够的空间,并且在存储和检索时回删除末尾的空格,而VARCHAR可以保留末尾的空格。MySQL 处理CHAR的速度比VARCHAR更快。

VARCHAR是可以变长串,VARCHARCHAR更节省空间(因为只使用必要的空间)。但执行UPDATE后行记录可能会变长,当超出一个页所能容纳的大小时,就需要执行额外的操作,MyISAM 会将行拆成不同的片段存储,InnoDB 则需要分裂页来使行放进页内。

当字符串列的长度比平均长度大很多时、列的更新很少时,使用VARCHAR类型更好;对于定长的字符串如 MD5、经常变更或者非常短的字符串(因为VARCHAR需要额外的 1 个或 2 个字节记录字符串长度)则使用CHAR类型更好。

日期和时间

MySQL 中有两种常用的日期类型:DATETIMETIMESTAMP

DATETIME格式为YYYY-MM-DD-HH:MM:SS,它把日期和时间封装到了相同的整数中,与时区无关,使用 8 个字节的存储空间。默认情况下,MySQL 以一种可排序的、无歧义的格式显示,例如2008-01-16 22:37:08

TIMESTAMP保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年到 2038 年。它可以自动检索当前时区并进行转换。默认情况下,如果插入时没有指定TIMESTAMP列的值,MySQL 则设置这个列的值为当前时间。

区别

  • 存储使用的字节数量不同,尽可能使用TIMESTAMP,因为它的空间效率高。
  • TIMESTAMP会进行时区的检索,如果储存时的时区和检索时的时区不一样,那么拿出来的数据也不一样。对于DATETIME来说,存什么拿到的就是什么。
  • 计算时间间隔时,DATETIME需要额外的转换,而TIMESTAMP直接相减就可以。

参考

  1. MySql:int(10) 与 int unsigned 之前的区别
  2. MySQL 常用数据类型-水木今山
  3. MySQL 之数据类型
  4. MySQL decimal 类型
  5. MySQL 中 datetime 和 timestamp 的区别与选择
  6. MySQL 时间类型 DATE、DATETIME 和 TIMESTAMP