整型
TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT分别使用了 1,2,3,4,8 字节的存储空间。
UNSIGNED关键字表示不允许插入负数并将正数的取值范围扩大了两倍,但是有符号数和无符号类型的存储空间和性能依旧是一样的。
MySQL 可以指定整型类型的显示宽度,例如INT(11)。显示宽度和数据类型的取值范围是无关的,只是证明了 MySQL 最大可能显示的数字个数。数值的位数小于指定的宽度会由空格填充;如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。
浮点数
FLOAT和DOUBLE分别为单精度(4 字节)和双精度(8 字节)的浮点数。DECIMAL 是精度可变的定点数,占用的字节由其精度 M 决定。
浮点数和定点数都可以指定精度,例如DECIMAL(11, 5)表示总共 11 位,取 5 位存储小数部分,剩下的 6 位存储整数部分,一种占用了 11+2=13 字节。
CPU 原生支持浮点运算,但不支持对DECIMAL的运算,因此浮点运算会更快。但是浮点数会引起精度问题,像货币这样对精度敏感的数据,在 MySQL 中一般使用DECIMAL(8, 2)来存储。
定点数和浮点数区别
- 在 MySQL 中,定点数以字符串形式存储,在对精度要求比较高的时候(如货币,科学数据等)使用
DECIMAL的类型比较好。 - 浮点数
FLOAT、DOUBLE相对于定点数DECIMAL的优势是在一定的情况下,浮点数能表示更大的范围数据。 - 浮点数的减法和比较运算容易产生误差,在使用浮点型需要注意尽量避免浮点数之间的比较。
字符串
MySQL 中主要使用的字符串数据类型有VARCHAR和CHAR。
CHAR是定长串,接收长度固定的字符串。MySQL 总是根据定义的字符串长度分配足够的空间,并且在存储和检索时回删除末尾的空格,而VARCHAR可以保留末尾的空格。MySQL 处理CHAR的速度比VARCHAR更快。
VARCHAR是可以变长串,VARCHAR比CHAR更节省空间(因为只使用必要的空间)。但执行UPDATE后行记录可能会变长,当超出一个页所能容纳的大小时,就需要执行额外的操作,MyISAM 会将行拆成不同的片段存储,InnoDB 则需要分裂页来使行放进页内。
当字符串列的长度比平均长度大很多时、列的更新很少时,使用VARCHAR类型更好;对于定长的字符串如 MD5、经常变更或者非常短的字符串(因为VARCHAR需要额外的 1 个或 2 个字节记录字符串长度)则使用CHAR类型更好。
日期和时间
MySQL 中有两种常用的日期类型:DATETIME和TIMESTAMP。
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直接相减就可以。